Salome HOME
Modification of the getHeapMemorySize computation.
[modules/med.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 "InterpKernelAutoPtr.hxx"
37 #include "InterpKernelGeo2DNode.hxx"
38 #include "InterpKernelGeo2DEdgeLin.hxx"
39 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
40 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
41
42 #include <sstream>
43 #include <fstream>
44 #include <numeric>
45 #include <cstring>
46 #include <limits>
47 #include <list>
48
49 using namespace ParaMEDMEM;
50
51 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
52
53 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 };
54
55 MEDCouplingUMesh *MEDCouplingUMesh::New()
56 {
57   return new MEDCouplingUMesh;
58 }
59
60 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
61 {
62   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
63   ret->setName(meshName);
64   ret->setMeshDimension(meshDim);
65   return ret;
66 }
67
68 /*!
69  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
70  * between \a this and the new mesh.
71  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
72  *          delete this mesh using decrRef() as it is no more needed. 
73  */
74 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
75 {
76   return clone(true);
77 }
78
79 /*!
80  * Returns a new MEDCouplingMesh which is a copy of \a this one.
81  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
82  * this mesh are shared by the new mesh.
83  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
84  *          delete this mesh using decrRef() as it is no more needed. 
85  */
86 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
87 {
88   return new MEDCouplingUMesh(*this,recDeepCpy);
89 }
90
91 /*!
92  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
93  * The coordinates are shared between \a this and the returned instance.
94  * 
95  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
96  * \sa MEDCouplingUMesh::deepCpy
97  */
98 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const throw(INTERP_KERNEL::Exception)
99 {
100   checkConnectivityFullyDefined();
101   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
102   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
103   ret->setConnectivity(c,ci);
104   return ret.retn();
105 }
106
107 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception)
108 {
109   if(!other)
110     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
111   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
112   if(!otherC)
113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
114   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
115   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
116 }
117
118 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
119 {
120   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
121   return ret;
122 }
123
124 std::vector<RefCountObject *> MEDCouplingUMesh::getDirectChildren() const
125 {
126   std::vector<RefCountObject *> ret(MEDCouplingPointSet::getDirectChildren());
127   if(_nodal_connec)
128     ret.push_back(const_cast<DataArrayInt *>(_nodal_connec));
129   if(_nodal_connec_index)
130     ret.push_back(const_cast<DataArrayInt *>(_nodal_connec_index));
131   return ret;
132 }
133
134 void MEDCouplingUMesh::updateTime() const
135 {
136   MEDCouplingPointSet::updateTime();
137   if(_nodal_connec)
138     {
139       updateTimeWith(*_nodal_connec);
140     }
141   if(_nodal_connec_index)
142     {
143       updateTimeWith(*_nodal_connec_index);
144     }
145 }
146
147 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
148 {
149 }
150
151 /*!
152  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
153  * then \a this mesh is most probably is writable, exchangeable and available for most
154  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
155  * this method to check that all is in order with \a this mesh.
156  *  \throw If the mesh dimension is not set.
157  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
158  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
159  *  \throw If the connectivity data array has more than one component.
160  *  \throw If the connectivity data array has a named component.
161  *  \throw If the connectivity index data array has more than one component.
162  *  \throw If the connectivity index data array has a named component.
163  */
164 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
165 {
166   if(_mesh_dim<-1)
167    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
168   if(_mesh_dim!=-1)
169     MEDCouplingPointSet::checkCoherency();
170   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
171     {
172       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
173         {
174           std::ostringstream message;
175           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
176           throw INTERP_KERNEL::Exception(message.str().c_str());
177         }
178     }
179   if(_nodal_connec)
180     {
181       if(_nodal_connec->getNumberOfComponents()!=1)
182         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
183       if(_nodal_connec->getInfoOnComponent(0)!="")
184         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
185     }
186   else
187     if(_mesh_dim!=-1)
188       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
189   if(_nodal_connec_index)
190     {
191       if(_nodal_connec_index->getNumberOfComponents()!=1)
192         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
193       if(_nodal_connec_index->getInfoOnComponent(0)!="")
194         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
195     }
196   else
197     if(_mesh_dim!=-1)
198       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
199 }
200
201 /*!
202  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
203  * then \a this mesh is most probably is writable, exchangeable and available for all
204  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
205  * method thoroughly checks the nodal connectivity.
206  *  \param [in] eps - a not used parameter.
207  *  \throw If the mesh dimension is not set.
208  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
209  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
210  *  \throw If the connectivity data array has more than one component.
211  *  \throw If the connectivity data array has a named component.
212  *  \throw If the connectivity index data array has more than one component.
213  *  \throw If the connectivity index data array has a named component.
214  *  \throw If number of nodes defining an element does not correspond to the type of element.
215  *  \throw If the nodal connectivity includes an invalid node id.
216  */
217 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
218 {
219   checkCoherency();
220   if(_mesh_dim==-1)
221     return ;
222   int meshDim=getMeshDimension();
223   int nbOfNodes=getNumberOfNodes();
224   int nbOfCells=getNumberOfCells();
225   const int *ptr=_nodal_connec->getConstPointer();
226   const int *ptrI=_nodal_connec_index->getConstPointer();
227   for(int i=0;i<nbOfCells;i++)
228     {
229       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
230       if((int)cm.getDimension()!=meshDim)
231         {
232           std::ostringstream oss;
233           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
234           throw INTERP_KERNEL::Exception(oss.str().c_str());
235         }
236       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
237       if(!cm.isDynamic())
238         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
239           {
240             std::ostringstream oss;
241             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
242             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
243             throw INTERP_KERNEL::Exception(oss.str().c_str());
244           }
245       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
246         {
247           int nodeId=*w;
248           if(nodeId>=0)
249             {
250               if(nodeId>=nbOfNodes)
251                 {
252                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
253                   throw INTERP_KERNEL::Exception(oss.str().c_str());
254                 }
255             }
256           else if(nodeId<-1)
257             {
258               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
259               throw INTERP_KERNEL::Exception(oss.str().c_str());
260             }
261           else
262             {
263               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
264                 {
265                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
266                   throw INTERP_KERNEL::Exception(oss.str().c_str());
267                 }
268             }
269         }
270     }
271 }
272
273
274 /*!
275  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
276  * then \a this mesh is most probably is writable, exchangeable and available for all
277  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
278  *  \param [in] eps - a not used parameter.
279  *  \throw If the mesh dimension is not set.
280  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
281  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
282  *  \throw If the connectivity data array has more than one component.
283  *  \throw If the connectivity data array has a named component.
284  *  \throw If the connectivity index data array has more than one component.
285  *  \throw If the connectivity index data array has a named component.
286  *  \throw If number of nodes defining an element does not correspond to the type of element.
287  *  \throw If the nodal connectivity includes an invalid node id.
288  */
289 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
290 {
291   checkCoherency1(eps);
292 }
293
294 /*!
295  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
296  * elements contained in the mesh. For more info on the mesh dimension see
297  * \ref MEDCouplingUMeshPage.
298  *  \param [in] meshDim - a new mesh dimension.
299  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
300  */
301 void MEDCouplingUMesh::setMeshDimension(int meshDim)
302 {
303   if(meshDim<-1 || meshDim>3)
304     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
305   _mesh_dim=meshDim;
306   declareAsNew();
307 }
308
309 /*!
310  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
311  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
312  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
313  *
314  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
315  *
316  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
317  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
318  */
319 void MEDCouplingUMesh::allocateCells(int nbOfCells)
320 {
321   if(nbOfCells<0)
322     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
323   if(_nodal_connec_index)
324     {
325       _nodal_connec_index->decrRef();
326     }
327   if(_nodal_connec)
328     {
329       _nodal_connec->decrRef();
330     }
331   _nodal_connec_index=DataArrayInt::New();
332   _nodal_connec_index->reserve(nbOfCells+1);
333   _nodal_connec_index->pushBackSilent(0);
334   _nodal_connec=DataArrayInt::New();
335   _nodal_connec->reserve(2*nbOfCells);
336   _types.clear();
337   declareAsNew();
338 }
339
340 /*!
341  * Appends a cell to the connectivity array. For deeper understanding what is
342  * happening see \ref MEDCouplingUMeshNodalConnectivity.
343  *  \param [in] type - type of cell to add.
344  *  \param [in] size - number of nodes constituting this cell.
345  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
346  * 
347  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
348  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
349  */
350 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
351 {
352   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
353   if(_nodal_connec_index==0)
354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
355   if((int)cm.getDimension()==_mesh_dim)
356     {
357       if(!cm.isDynamic())
358         if(size!=(int)cm.getNumberOfNodes())
359           {
360             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
361             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
362             throw INTERP_KERNEL::Exception(oss.str().c_str());
363           }
364       int idx=_nodal_connec_index->back();
365       int val=idx+size+1;
366       _nodal_connec_index->pushBackSilent(val);
367       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
368       _types.insert(type);
369     }
370   else
371     {
372       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
373       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
374       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
375       throw INTERP_KERNEL::Exception(oss.str().c_str());
376     }
377 }
378
379 /*!
380  * Compacts data arrays to release unused memory. This method is to be called after
381  * finishing cell insertion using \a this->insertNextCell().
382  * 
383  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
384  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
385  */
386 void MEDCouplingUMesh::finishInsertingCells()
387 {
388   _nodal_connec->pack();
389   _nodal_connec_index->pack();
390   _nodal_connec->declareAsNew();
391   _nodal_connec_index->declareAsNew();
392   updateTime();
393 }
394
395 /*!
396  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
397  * Useful for python users.
398  */
399 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
400 {
401   return new MEDCouplingUMeshCellIterator(this);
402 }
403
404 /*!
405  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
406  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
407  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
408  * Useful for python users.
409  */
410 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
411 {
412   if(!checkConsecutiveCellTypes())
413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
414   return new MEDCouplingUMeshCellByTypeEntry(this);
415 }
416
417 /*!
418  * Returns a set of all cell types available in \a this mesh.
419  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
420  * \warning this method does not throw any exception even if \a this is not defined.
421  */
422 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
423 {
424   return _types;
425 }
426
427 /*!
428  * This method is a method that compares \a this and \a other.
429  * This method compares \b all attributes, even names and component names.
430  */
431 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
432 {
433   if(!other)
434     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
435   std::ostringstream oss; oss.precision(15);
436   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
437   if(!otherC)
438     {
439       reason="mesh given in input is not castable in MEDCouplingUMesh !";
440       return false;
441     }
442   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
443     return false;
444   if(_mesh_dim!=otherC->_mesh_dim)
445     {
446       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
447       reason=oss.str();
448       return false;
449     }
450   if(_types!=otherC->_types)
451     {
452       oss << "umesh geometric type mismatch :\nThis geometric types are :";
453       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
454         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
455       oss << "\nOther geometric types are :";
456       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
457         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
458       reason=oss.str();
459       return false;
460     }
461   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
462     if(_nodal_connec==0 || otherC->_nodal_connec==0)
463       {
464         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
465         return false;
466       }
467   if(_nodal_connec!=otherC->_nodal_connec)
468     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
469       {
470         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
471         return false;
472       }
473   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
474     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
475       {
476         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
477         return false;
478       }
479   if(_nodal_connec_index!=otherC->_nodal_connec_index)
480     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
481       {
482         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
483         return false;
484       }
485   return true;
486 }
487
488 /*!
489  * Checks if data arrays of this mesh (node coordinates, nodal
490  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
491  * not considered.
492  *  \param [in] other - the mesh to compare with.
493  *  \param [in] prec - precision value used to compare node coordinates.
494  *  \return bool - \a true if the two meshes are same.
495  */
496 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
497 {
498   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
499   if(!otherC)
500     return false;
501   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
502     return false;
503   if(_mesh_dim!=otherC->_mesh_dim)
504     return false;
505   if(_types!=otherC->_types)
506     return false;
507   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
508     if(_nodal_connec==0 || otherC->_nodal_connec==0)
509       return false;
510   if(_nodal_connec!=otherC->_nodal_connec)
511     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
512       return false;
513   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
514     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
515       return false;
516   if(_nodal_connec_index!=otherC->_nodal_connec_index)
517     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
518       return false;
519   return true;
520 }
521
522 /*!
523  * Checks if \a this and \a other meshes are geometrically equivalent with high
524  * probability, else an exception is thrown. The meshes are considered equivalent if
525  * (1) meshes contain the same number of nodes and the same number of elements of the
526  * same types (2) three cells of the two meshes (first, last and middle) are based
527  * on coincident nodes (with a specified precision).
528  *  \param [in] other - the mesh to compare with.
529  *  \param [in] prec - the precision used to compare nodes of the two meshes.
530  *  \throw If the two meshes do not match.
531  */
532 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
533 {
534  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
535  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
536   if(!otherC)
537     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
538 }
539
540 /*!
541  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
542  * cells each node belongs to.
543  * \warning For speed reasons, this method does not check if node ids in the nodal
544  *          connectivity correspond to the size of node coordinates array.
545  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
546  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
547  *        dividing cell ids in \a revNodal into groups each referring to one
548  *        node. Its every element (except the last one) is an index pointing to the
549  *         first id of a group of cells. For example cells sharing the node #1 are 
550  *        described by following range of indices: 
551  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
552  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
553  *        Number of cells sharing the *i*-th node is
554  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
555  * \throw If the coordinates array is not set.
556  * \throw If the nodal connectivity of cells is not defined.
557  * 
558  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
559  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
560  */
561 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
562 {
563   checkFullyDefined();
564   int nbOfNodes=getNumberOfNodes();
565   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
566   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
567   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
568   const int *conn=_nodal_connec->getConstPointer();
569   const int *connIndex=_nodal_connec_index->getConstPointer();
570   int nbOfCells=getNumberOfCells();
571   int nbOfEltsInRevNodal=0;
572   for(int eltId=0;eltId<nbOfCells;eltId++)
573     {
574       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
575       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
576       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
577         if(*iter>=0)//for polyhedrons
578           {
579             nbOfEltsInRevNodal++;
580             revNodalIndxPtr[(*iter)+1]++;
581           }
582     }
583   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
584   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
585   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
586   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
587   for(int eltId=0;eltId<nbOfCells;eltId++)
588     {
589       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
590       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
591       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
592         if(*iter>=0)//for polyhedrons
593           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
594     }
595 }
596
597 /// @cond INTERNAL
598
599 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
600 {
601   return id;
602 }
603
604 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
605 {
606   if(!compute)
607     return id+1;
608   else
609     {
610       if(cm.getOrientationStatus(nb,conn1,conn2))
611         return id+1;
612       else
613         return -(id+1);
614     }
615 }
616
617 class MinusOneSonsGenerator
618 {
619 public:
620   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
621   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
622   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
623   static const int DELTA=1;
624 private:
625   const INTERP_KERNEL::CellModel& _cm;
626 };
627
628 class MinusOneSonsGeneratorBiQuadratic
629 {
630 public:
631   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
632   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
633   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
634   static const int DELTA=1;
635 private:
636   const INTERP_KERNEL::CellModel& _cm;
637 };
638
639 class MinusTwoSonsGenerator
640 {
641 public:
642   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
643   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
644   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
645   static const int DELTA=2;
646 private:
647   const INTERP_KERNEL::CellModel& _cm;
648 };
649
650 /// @endcond
651
652 /*!
653  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
654  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
655  * describing correspondence between cells of \a this and the result meshes are
656  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
657  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
658  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
659  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
660  * \warning For speed reasons, this method does not check if node ids in the nodal
661  *          connectivity correspond to the size of node coordinates array.
662  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
663  *          to write this mesh to the MED file, its cells must be sorted using
664  *          sortCellsInMEDFileFrmt().
665  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
666  *         each cell of \a this mesh.
667  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
668  *        dividing cell ids in \a desc into groups each referring to one
669  *        cell of \a this mesh. Its every element (except the last one) is an index
670  *        pointing to the first id of a group of cells. For example cells of the
671  *        result mesh bounding the cell #1 of \a this mesh are described by following
672  *        range of indices:
673  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
674  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
675  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
676  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
677  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
678  *         by each cell of the result mesh.
679  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
680  *        in the result mesh,
681  *        dividing cell ids in \a revDesc into groups each referring to one
682  *        cell of the result mesh the same way as \a descIndx divides \a desc.
683  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
684  *        delete this mesh using decrRef() as it is no more needed.
685  *  \throw If the coordinates array is not set.
686  *  \throw If the nodal connectivity of cells is node defined.
687  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
688  *         revDescIndx == NULL.
689  * 
690  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
691  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
692  * \sa buildDescendingConnectivity2()
693  */
694 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
695 {
696   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
697 }
698
699 /*!
700  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
701  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
702  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
703  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
704  * \sa MEDCouplingUMesh::buildDescendingConnectivity
705  */
706 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
707 {
708   checkFullyDefined();
709   if(getMeshDimension()!=3)
710     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
711   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
712 }
713
714 /*!
715  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
716  * this->getMeshDimension(), that bound cells of \a this mesh. In
717  * addition arrays describing correspondence between cells of \a this and the result
718  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
719  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
720  *  mesh. This method differs from buildDescendingConnectivity() in that apart
721  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
722  * result meshes. So a positive id means that order of nodes in corresponding cells
723  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
724  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
725  * i.e. cell ids are one-based.
726  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
727  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
728  * \warning For speed reasons, this method does not check if node ids in the nodal
729  *          connectivity correspond to the size of node coordinates array.
730  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
731  *          to write this mesh to the MED file, its cells must be sorted using
732  *          sortCellsInMEDFileFrmt().
733  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
734  *         each cell of \a this mesh.
735  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
736  *        dividing cell ids in \a desc into groups each referring to one
737  *        cell of \a this mesh. Its every element (except the last one) is an index
738  *        pointing to the first id of a group of cells. For example cells of the
739  *        result mesh bounding the cell #1 of \a this mesh are described by following
740  *        range of indices:
741  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
742  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
743  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
744  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
745  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
746  *         by each cell of the result mesh.
747  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
748  *        in the result mesh,
749  *        dividing cell ids in \a revDesc into groups each referring to one
750  *        cell of the result mesh the same way as \a descIndx divides \a desc.
751  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
752  *        shares the node coordinates array with \a this mesh. The caller is to
753  *        delete this mesh using decrRef() as it is no more needed.
754  *  \throw If the coordinates array is not set.
755  *  \throw If the nodal connectivity of cells is node defined.
756  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
757  *         revDescIndx == NULL.
758  * 
759  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
760  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
761  * \sa buildDescendingConnectivity()
762  */
763 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
764 {
765   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
766 }
767
768 /*!
769  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
770  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
771  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
772  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
773  *
774  * \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
775  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
776  * \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.
777  */
778 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
779 {
780   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
781   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
782   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
783   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
784   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
785   meshDM1=0;
786   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
787 }
788
789 /*!
790  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
791  * 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,
792  * excluding a set of meshdim-1 cells in input descending connectivity.
793  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
794  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
795  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
796  *
797  * \param [in] desc descending connectivity array.
798  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
799  * \param [in] revDesc reverse descending connectivity array.
800  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
801  * \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
802  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
803  * \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.
804  */
805 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
806                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
807 {
808   if(!desc || !descIndx || !revDesc || !revDescIndx)
809     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
810   const int *descPtr=desc->getConstPointer();
811   const int *descIPtr=descIndx->getConstPointer();
812   const int *revDescPtr=revDesc->getConstPointer();
813   const int *revDescIPtr=revDescIndx->getConstPointer();
814   //
815   int nbCells=descIndx->getNumberOfTuples()-1;
816   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
817   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
818   int *out1Ptr=out1->getPointer();
819   *out1Ptr++=0;
820   out0->reserve(desc->getNumberOfTuples());
821   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
822     {
823       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
824         {
825           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
826           s.erase(i);
827           out0->insertAtTheEnd(s.begin(),s.end());
828         }
829       *out1Ptr=out0->getNumberOfTuples();
830     }
831   neighbors=out0.retn();
832   neighborsIndx=out1.retn();
833 }
834
835 /// @cond INTERNAL
836
837 /*!
838  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
839  * For speed reasons no check of this will be done.
840  */
841 template<class SonsGenerator>
842 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
843 {
844   if(!desc || !descIndx || !revDesc || !revDescIndx)
845     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
846   checkConnectivityFullyDefined();
847   int nbOfCells=getNumberOfCells();
848   int nbOfNodes=getNumberOfNodes();
849   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
850   int *revNodalIndxPtr=revNodalIndx->getPointer();
851   const int *conn=_nodal_connec->getConstPointer();
852   const int *connIndex=_nodal_connec_index->getConstPointer();
853   std::string name="Mesh constituent of "; name+=getName();
854   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
855   ret->setCoords(getCoords());
856   ret->allocateCells(2*nbOfCells);
857   descIndx->alloc(nbOfCells+1,1);
858   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
859   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
860   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
861     {
862       int pos=connIndex[eltId];
863       int posP1=connIndex[eltId+1];
864       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
865       SonsGenerator sg(cm);
866       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
867       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
868       for(unsigned i=0;i<nbOfSons;i++)
869         {
870           INTERP_KERNEL::NormalizedCellType cmsId;
871           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
872           for(unsigned k=0;k<nbOfNodesSon;k++)
873             if(tmp[k]>=0)
874               revNodalIndxPtr[tmp[k]+1]++;
875           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
876           revDesc2->pushBackSilent(eltId);
877         }
878       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
879     }
880   int nbOfCellsM1=ret->getNumberOfCells();
881   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
883   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
884   int *revNodalPtr=revNodal->getPointer();
885   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
886   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
887   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
888     {
889       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
890       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
891       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
892         if(*iter>=0)//for polyhedrons
893           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
894     }
895   //
896   DataArrayInt *commonCells=0,*commonCellsI=0;
897   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
898   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
899   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
900   int newNbOfCellsM1=-1;
901   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
902                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
903   std::vector<bool> isImpacted(nbOfCellsM1,false);
904   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
905     for(int work2=work[0];work2!=work[1];work2++)
906       isImpacted[commonCellsPtr[work2]]=true;
907   const int *o2nM1Ptr=o2nM1->getConstPointer();
908   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
909   const int *n2oM1Ptr=n2oM1->getConstPointer();
910   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
911   ret2->copyTinyInfoFrom(this);
912   desc->alloc(descIndx->back(),1);
913   int *descPtr=desc->getPointer();
914   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
915   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
916     {
917       if(!isImpacted[i])
918         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
919       else
920         {
921           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
922             {
923               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
924               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
925             }
926           else
927             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
928         }
929     }
930   revDesc->reserve(newNbOfCellsM1);
931   revDescIndx->alloc(newNbOfCellsM1+1,1);
932   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
933   const int *revDesc2Ptr=revDesc2->getConstPointer();
934   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
935     {
936       int oldCellIdM1=n2oM1Ptr[i];
937       if(!isImpacted[oldCellIdM1])
938         {
939           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
940           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
941         }
942       else
943         {
944           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
945             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
946           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
947           commonCellsIPtr++;
948         }
949     }
950   //
951   return ret2.retn();
952 }
953
954 struct MEDCouplingAccVisit
955 {
956   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
957   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
958   int _new_nb_of_nodes;
959 };
960
961 /// @endcond
962
963 /*!
964  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
965  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
966  * array of cell ids. Pay attention that after conversion all algorithms work slower
967  * with \a this mesh than before conversion. <br> If an exception is thrown during the
968  * conversion due presence of invalid ids in the array of cells to convert, as a
969  * result \a this mesh contains some already converted elements. In this case the 2D
970  * mesh remains valid but 3D mesh becomes \b inconsistent!
971  *  \warning This method can significantly modify the order of geometric types in \a this,
972  *          hence, to write this mesh to the MED file, its cells must be sorted using
973  *          sortCellsInMEDFileFrmt().
974  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
975  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
976  *         cellIdsToConvertBg.
977  *  \throw If the coordinates array is not set.
978  *  \throw If the nodal connectivity of cells is node defined.
979  *  \throw If dimension of \a this mesh is not either 2 or 3.
980  *
981  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
982  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
983  */
984 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
985 {
986   checkFullyDefined();
987   int dim=getMeshDimension();
988   if(dim<2 || dim>3)
989     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
990   int nbOfCells=getNumberOfCells();
991   if(dim==2)
992     {
993       const int *connIndex=_nodal_connec_index->getConstPointer();
994       int *conn=_nodal_connec->getPointer();
995       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
996         {
997           if(*iter>=0 && *iter<nbOfCells)
998             {
999               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1000               if(!cm.isQuadratic())
1001                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1002               else
1003                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1004             }
1005           else
1006             {
1007               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1008               oss << " in range [0," << nbOfCells << ") !";
1009               throw INTERP_KERNEL::Exception(oss.str().c_str());
1010             }
1011         }
1012     }
1013   else
1014     {
1015       int *connIndex=_nodal_connec_index->getPointer();
1016       int connIndexLgth=_nodal_connec_index->getNbOfElems();
1017       const int *connOld=_nodal_connec->getConstPointer();
1018       int connOldLgth=_nodal_connec->getNbOfElems();
1019       std::vector<int> connNew(connOld,connOld+connOldLgth);
1020       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1021         {
1022           if(*iter>=0 && *iter<nbOfCells)
1023             {
1024               int pos=connIndex[*iter];
1025               int posP1=connIndex[(*iter)+1];
1026               int lgthOld=posP1-pos-1;
1027               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1028               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1029               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1030               int *tmp=new int[nbOfFaces*lgthOld];
1031               int *work=tmp;
1032               for(int j=0;j<(int)nbOfFaces;j++)
1033                 {
1034                   INTERP_KERNEL::NormalizedCellType type;
1035                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1036                   work+=offset;
1037                   *work++=-1;
1038                 }
1039               std::size_t newLgth=std::distance(tmp,work)-1;
1040               std::size_t delta=newLgth-lgthOld;
1041               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1042               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1043               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1044               delete [] tmp;
1045             }
1046           else
1047             {
1048               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1049               oss << " in range [0," << nbOfCells << ") !";
1050               throw INTERP_KERNEL::Exception(oss.str().c_str());
1051             }
1052         }
1053       _nodal_connec->alloc((int)connNew.size(),1);
1054       int *newConnPtr=_nodal_connec->getPointer();
1055       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1056     }
1057   computeTypes();
1058 }
1059
1060 /*!
1061  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1062  * polyhedrons (if \a this is a 3D mesh).
1063  *  \warning As this method is purely for user-friendliness and no optimization is
1064  *          done to avoid construction of a useless vector, this method can be costly
1065  *          in memory.
1066  *  \throw If the coordinates array is not set.
1067  *  \throw If the nodal connectivity of cells is node defined.
1068  *  \throw If dimension of \a this mesh is not either 2 or 3.
1069  */
1070 void MEDCouplingUMesh::convertAllToPoly()
1071 {
1072   int nbOfCells=getNumberOfCells();
1073   std::vector<int> cellIds(nbOfCells);
1074   for(int i=0;i<nbOfCells;i++)
1075     cellIds[i]=i;
1076   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1077 }
1078
1079 /*!
1080  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1081  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1082  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1083  * base facet of the volume and the second half of nodes describes an opposite facet
1084  * having the same number of nodes as the base one. This method converts such
1085  * connectivity to a valid polyhedral format where connectivity of each facet is
1086  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1087  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1088  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1089  * a correct orientation of the first facet of a polyhedron, else orientation of a
1090  * corrected cell is reverse.<br>
1091  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1092  * it releases the user from boring description of polyhedra connectivity in the valid
1093  * format.
1094  *  \throw If \a this->getMeshDimension() != 3.
1095  *  \throw If \a this->getSpaceDimension() != 3.
1096  *  \throw If the nodal connectivity of cells is not defined.
1097  *  \throw If the coordinates array is not set.
1098  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1099  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1100  *
1101  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1102  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1103  */
1104 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1105 {
1106   checkFullyDefined();
1107   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1108     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1109   int nbOfCells=getNumberOfCells();
1110   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1111   newCi->alloc(nbOfCells+1,1);
1112   int *newci=newCi->getPointer();
1113   const int *ci=_nodal_connec_index->getConstPointer();
1114   const int *c=_nodal_connec->getConstPointer();
1115   newci[0]=0;
1116   for(int i=0;i<nbOfCells;i++)
1117     {
1118       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1119       if(type==INTERP_KERNEL::NORM_POLYHED)
1120         {
1121           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1122             {
1123               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1124               throw INTERP_KERNEL::Exception(oss.str().c_str());
1125             }
1126           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1127           if(n2%2!=0)
1128             {
1129               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 !";
1130               throw INTERP_KERNEL::Exception(oss.str().c_str());
1131             }
1132           int n1=(int)(n2/2);
1133           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)
1134         }
1135       else
1136         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1137     }
1138   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1139   newC->alloc(newci[nbOfCells],1);
1140   int *newc=newC->getPointer();
1141   for(int i=0;i<nbOfCells;i++)
1142     {
1143       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1144       if(type==INTERP_KERNEL::NORM_POLYHED)
1145         {
1146           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1147           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1148           *newc++=-1;
1149           for(std::size_t j=0;j<n1;j++)
1150             {
1151               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1152               newc[n1+5*j]=-1;
1153               newc[n1+5*j+1]=c[ci[i]+1+j];
1154               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1155               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1156               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1157             }
1158           newc+=n1*6;
1159         }
1160       else
1161         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1162     }
1163   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1164   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1165 }
1166
1167
1168 /*!
1169  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1170  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1171  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1172  *          to write this mesh to the MED file, its cells must be sorted using
1173  *          sortCellsInMEDFileFrmt().
1174  * \return \c true if at least one cell has been converted, \c false else. In the
1175  *         last case the nodal connectivity remains unchanged.
1176  * \throw If the coordinates array is not set.
1177  * \throw If the nodal connectivity of cells is not defined.
1178  * \throw If \a this->getMeshDimension() < 0.
1179  */
1180 bool MEDCouplingUMesh::unPolyze()
1181 {
1182   checkFullyDefined();
1183   int mdim=getMeshDimension();
1184   if(mdim<0)
1185     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1186   if(mdim<=1)
1187     return false;
1188   int nbOfCells=getNumberOfCells();
1189   if(nbOfCells<1)
1190     return false;
1191   int initMeshLgth=getMeshLength();
1192   int *conn=_nodal_connec->getPointer();
1193   int *index=_nodal_connec_index->getPointer();
1194   int posOfCurCell=0;
1195   int newPos=0;
1196   int lgthOfCurCell;
1197   bool ret=false;
1198   for(int i=0;i<nbOfCells;i++)
1199     {
1200       lgthOfCurCell=index[i+1]-posOfCurCell;
1201       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1202       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1203       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1204       int newLgth;
1205       if(cm.isDynamic())
1206         {
1207           switch(cm.getDimension())
1208             {
1209             case 2:
1210               {
1211                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1212                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1213                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1214                 break;
1215               }
1216             case 3:
1217               {
1218                 int nbOfFaces,lgthOfPolyhConn;
1219                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1220                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1221                 break;
1222               }
1223             case 1:
1224               {
1225                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1226                 break;
1227               }
1228             }
1229           ret=ret || (newType!=type);
1230           conn[newPos]=newType;
1231           newPos+=newLgth+1;
1232           posOfCurCell=index[i+1];
1233           index[i+1]=newPos;
1234         }
1235       else
1236         {
1237           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1238           newPos+=lgthOfCurCell;
1239           posOfCurCell+=lgthOfCurCell;
1240           index[i+1]=newPos;
1241         }
1242     }
1243   if(newPos!=initMeshLgth)
1244     _nodal_connec->reAlloc(newPos);
1245   if(ret)
1246     computeTypes();
1247   return ret;
1248 }
1249
1250 /*!
1251  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1252  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1253  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1254  *
1255  * \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 
1256  *             precision.
1257  */
1258 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1259 {
1260   checkFullyDefined();
1261   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1262     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1263   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1264   coords->recenterForMaxPrecision(eps);
1265   //
1266   int nbOfCells=getNumberOfCells();
1267   const int *conn=_nodal_connec->getConstPointer();
1268   const int *index=_nodal_connec_index->getConstPointer();
1269   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1270   connINew->alloc(nbOfCells+1,1);
1271   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1273   bool changed=false;
1274   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1275     {
1276       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1277         {
1278           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1279           changed=true;
1280         }
1281       else
1282         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1283       *connINewPtr=connNew->getNumberOfTuples();
1284     }
1285   if(changed)
1286     setConnectivity(connNew,connINew,false);
1287 }
1288
1289 /*!
1290  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1291  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1292  * the format of returned DataArrayInt instance.
1293  * 
1294  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1295  * \sa MEDCouplingUMesh::getNodeIdsInUse
1296  */
1297 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1298 {
1299   checkConnectivityFullyDefined();
1300   int nbOfCells=getNumberOfCells();
1301   const int *connIndex=_nodal_connec_index->getConstPointer();
1302   const int *conn=_nodal_connec->getConstPointer();
1303   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1304   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1305   std::vector<bool> retS(maxElt,false);
1306   for(int i=0;i<nbOfCells;i++)
1307     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1308       if(conn[j]>=0)
1309         retS[conn[j]]=true;
1310   int sz=0;
1311   for(int i=0;i<maxElt;i++)
1312     if(retS[i])
1313       sz++;
1314   DataArrayInt *ret=DataArrayInt::New();
1315   ret->alloc(sz,1);
1316   int *retPtr=ret->getPointer();
1317   for(int i=0;i<maxElt;i++)
1318     if(retS[i])
1319       *retPtr++=i;
1320   return ret;
1321 }
1322
1323 /*!
1324  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1325  * \sa MEDCouplingUMesh::getNodeIdsInUse
1326  */
1327 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1328 {
1329   int nbOfNodes=(int)nodeIdsInUse.size();
1330   int nbOfCells=getNumberOfCells();
1331   const int *connIndex=_nodal_connec_index->getConstPointer();
1332   const int *conn=_nodal_connec->getConstPointer();
1333   for(int i=0;i<nbOfCells;i++)
1334     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1335       if(conn[j]>=0)
1336         {
1337           if(conn[j]<nbOfNodes)
1338             nodeIdsInUse[conn[j]]=true;
1339           else
1340             {
1341               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1342               throw INTERP_KERNEL::Exception(oss.str().c_str());
1343             }
1344         }
1345 }
1346
1347 /*!
1348  * Finds nodes not used in any cell and returns an array giving a new id to every node
1349  * by excluding the unused nodes, for which the array holds -1. The result array is
1350  * a mapping in "Old to New" mode. 
1351  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1352  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1353  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1354  *          if the node is unused or a new id else. The caller is to delete this
1355  *          array using decrRef() as it is no more needed.  
1356  *  \throw If the coordinates array is not set.
1357  *  \throw If the nodal connectivity of cells is not defined.
1358  *  \throw If the nodal connectivity includes an invalid id.
1359  *
1360  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1361  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1362  * \sa computeNodeIdsAlg()
1363  */
1364 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1365 {
1366   nbrOfNodesInUse=-1;
1367   int nbOfNodes=getNumberOfNodes();
1368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1369   ret->alloc(nbOfNodes,1);
1370   int *traducer=ret->getPointer();
1371   std::fill(traducer,traducer+nbOfNodes,-1);
1372   int nbOfCells=getNumberOfCells();
1373   const int *connIndex=_nodal_connec_index->getConstPointer();
1374   const int *conn=_nodal_connec->getConstPointer();
1375   for(int i=0;i<nbOfCells;i++)
1376     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1377       if(conn[j]>=0)
1378         {
1379           if(conn[j]<nbOfNodes)
1380             traducer[conn[j]]=1;
1381           else
1382             {
1383               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1384               throw INTERP_KERNEL::Exception(oss.str().c_str());
1385             }
1386         }
1387   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1388   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1389   return ret.retn();
1390 }
1391
1392 /*!
1393  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1394  * For each cell in \b this the number of nodes constituting cell is computed.
1395  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1396  * So for pohyhedrons some nodes can be counted several times in the returned result.
1397  * 
1398  * \return a newly allocated array
1399  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1400  */
1401 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1402 {
1403   checkConnectivityFullyDefined();
1404   int nbOfCells=getNumberOfCells();
1405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1406   ret->alloc(nbOfCells,1);
1407   int *retPtr=ret->getPointer();
1408   const int *conn=getNodalConnectivity()->getConstPointer();
1409   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1410   for(int i=0;i<nbOfCells;i++,retPtr++)
1411     {
1412       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1413         *retPtr=connI[i+1]-connI[i]-1;
1414       else
1415         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1416     }
1417   return ret.retn();
1418 }
1419
1420 /*!
1421  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1422  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1423  *
1424  * \return DataArrayInt * - new object to be deallocated by the caller.
1425  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1426  */
1427 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1428 {
1429   checkConnectivityFullyDefined();
1430   int nbOfCells=getNumberOfCells();
1431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1432   ret->alloc(nbOfCells,1);
1433   int *retPtr=ret->getPointer();
1434   const int *conn=getNodalConnectivity()->getConstPointer();
1435   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1436   for(int i=0;i<nbOfCells;i++,retPtr++)
1437     {
1438       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1439       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1440         *retPtr=(int)s.size();
1441       else
1442         {
1443           s.erase(-1);
1444           *retPtr=(int)s.size();
1445         }
1446     }
1447   return ret.retn();
1448 }
1449
1450 /*!
1451  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1452  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1453  * 
1454  * \return a newly allocated array
1455  */
1456 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1457 {
1458   checkConnectivityFullyDefined();
1459   int nbOfCells=getNumberOfCells();
1460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1461   ret->alloc(nbOfCells,1);
1462   int *retPtr=ret->getPointer();
1463   const int *conn=getNodalConnectivity()->getConstPointer();
1464   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1465   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1466     {
1467       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1468       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1469     }
1470   return ret.retn();
1471 }
1472
1473 /*!
1474  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1475  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1476  * array mean that the corresponding old node is no more used. 
1477  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1478  *           this->getNumberOfNodes() before call of this method. The caller is to
1479  *           delete this array using decrRef() as it is no more needed. 
1480  *  \throw If the coordinates array is not set.
1481  *  \throw If the nodal connectivity of cells is not defined.
1482  *  \throw If the nodal connectivity includes an invalid id.
1483  *
1484  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1485  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1486  */
1487 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1488 {
1489   return MEDCouplingPointSet::zipCoordsTraducer();
1490 }
1491
1492 /*!
1493  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1494  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1495  */
1496 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1497 {
1498   switch(compType)
1499     {
1500     case 0:
1501       return AreCellsEqual0(conn,connI,cell1,cell2);
1502     case 1:
1503       return AreCellsEqual1(conn,connI,cell1,cell2);
1504     case 2:
1505       return AreCellsEqual2(conn,connI,cell1,cell2);
1506     case 3:
1507       return AreCellsEqual3(conn,connI,cell1,cell2);
1508     case 7:
1509       return AreCellsEqual7(conn,connI,cell1,cell2);
1510     }
1511   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1512 }
1513
1514 /*!
1515  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1516  */
1517 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1518 {
1519   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1520     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1521   return 0;
1522 }
1523
1524 /*!
1525  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1526  */
1527 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1528 {
1529   int sz=connI[cell1+1]-connI[cell1];
1530   if(sz==connI[cell2+1]-connI[cell2])
1531     {
1532       if(conn[connI[cell1]]==conn[connI[cell2]])
1533         {
1534           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1535           unsigned dim=cm.getDimension();
1536           if(dim!=3)
1537             {
1538               if(dim!=1)
1539                 {
1540                   int sz1=2*(sz-1);
1541                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1542                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1543                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1544                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1545                   return work!=tmp+sz1?1:0;
1546                 }
1547               else
1548                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1549             }
1550           else
1551             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1552         }
1553     }
1554   return 0;
1555 }
1556
1557 /*!
1558  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1559  */
1560 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1561 {
1562   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1563     {
1564       if(conn[connI[cell1]]==conn[connI[cell2]])
1565         {
1566           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1567           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1568           return s1==s2?1:0;
1569         }
1570     }
1571   return 0;
1572 }
1573
1574 /*!
1575  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1576  */
1577 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1578 {
1579   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1580     {
1581       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1582       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1583       return s1==s2?1:0;
1584     }
1585   return 0;
1586 }
1587
1588 /*!
1589  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1590  */
1591 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1592 {
1593   int sz=connI[cell1+1]-connI[cell1];
1594   if(sz==connI[cell2+1]-connI[cell2])
1595     {
1596       if(conn[connI[cell1]]==conn[connI[cell2]])
1597         {
1598           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1599           unsigned dim=cm.getDimension();
1600           if(dim!=3)
1601             {
1602               if(dim!=1)
1603                 {
1604                   int sz1=2*(sz-1);
1605                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1606                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1607                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1608                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1609                   if(work!=tmp+sz1)
1610                     return 1;
1611                   else
1612                     {
1613                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1614                       std::reverse_iterator<int *> it2((int *)tmp);
1615                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1616                         return 2;
1617                       else
1618                         return 0;
1619                     }
1620                   
1621                   return work!=tmp+sz1?1:0;
1622                 }
1623               else
1624                 {//case of SEG2 and SEG3
1625                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1626                     return 1;
1627                   if(!cm.isQuadratic())
1628                     {
1629                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1630                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1631                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1632                         return 2;
1633                       return 0;
1634                     }
1635                   else
1636                     {
1637                       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])
1638                         return 2;
1639                       return 0;
1640                     }
1641                 }
1642             }
1643           else
1644             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1645         }
1646     }
1647   return 0;
1648 }
1649
1650 /*!
1651  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1652  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1653  * and result remains unchanged.
1654  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1655  * If in 'candidates' pool -1 value is considered as an empty value.
1656  * WARNING this method returns only ONE set of result !
1657  */
1658 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1659 {
1660   if(candidates.size()<1)
1661     return false;
1662   bool ret=false;
1663   std::vector<int>::const_iterator iter=candidates.begin();
1664   int start=(*iter++);
1665   for(;iter!=candidates.end();iter++)
1666     {
1667       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1668       if(status!=0)
1669         {
1670           if(!ret)
1671             {
1672               result->pushBackSilent(start);
1673               ret=true;
1674             }
1675           if(status==1)
1676             result->pushBackSilent(*iter);
1677           else
1678             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1679         }
1680     }
1681   return ret;
1682 }
1683
1684 /*!
1685  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1686  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1687  *
1688  * \param [in] compType input specifying the technique used to compare cells each other.
1689  *   - 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.
1690  *   - 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)
1691  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1692  *   - 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
1693  * can be used for users not sensitive to orientation of cell
1694  * \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.
1695  * \param [out] commonCells
1696  * \param [out] commonCellsI
1697  * \return the correspondance array old to new in a newly allocated array.
1698  * 
1699  */
1700 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1701 {
1702   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1703   getReverseNodalConnectivity(revNodal,revNodalI);
1704   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1705 }
1706
1707 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1708                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1709 {
1710   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1711   int nbOfCells=nodalI->getNumberOfTuples()-1;
1712   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1713   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1714   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1715   std::vector<bool> isFetched(nbOfCells,false);
1716   if(startCellId==0)
1717     {
1718       for(int i=0;i<nbOfCells;i++)
1719         {
1720           if(!isFetched[i])
1721             {
1722               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1723               std::vector<int> v,v2;
1724               if(connOfNode!=connPtr+connIPtr[i+1])
1725                 {
1726                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1727                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1728                   connOfNode++;
1729                 }
1730               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1731                 if(*connOfNode>=0)
1732                   {
1733                     v=v2;
1734                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1735                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1736                     v2.resize(std::distance(v2.begin(),it));
1737                   }
1738               if(v2.size()>1)
1739                 {
1740                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1741                     {
1742                       int pos=commonCellsI->back();
1743                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1744                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1745                         isFetched[*it]=true;
1746                     }
1747                 }
1748             }
1749         }
1750     }
1751   else
1752     {
1753       for(int i=startCellId;i<nbOfCells;i++)
1754         {
1755           if(!isFetched[i])
1756             {
1757               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1758               std::vector<int> v,v2;
1759               if(connOfNode!=connPtr+connIPtr[i+1])
1760                 {
1761                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1762                   connOfNode++;
1763                 }
1764               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1765                 if(*connOfNode>=0)
1766                   {
1767                     v=v2;
1768                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1769                     v2.resize(std::distance(v2.begin(),it));
1770                   }
1771               if(v2.size()>1)
1772                 {
1773                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1774                     {
1775                       int pos=commonCellsI->back();
1776                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1777                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1778                         isFetched[*it]=true;
1779                     }
1780                 }
1781             }
1782         }
1783     }
1784   commonCellsArr=commonCells.retn();
1785   commonCellsIArr=commonCellsI.retn();
1786 }
1787
1788 /*!
1789  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1790  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1791  * than \a other->getNumberOfCells() in the returned array means that there is no
1792  * corresponding cell in \a this mesh.
1793  * It is expected that \a this and \a other meshes share the same node coordinates
1794  * array, if it is not so an exception is thrown. 
1795  *  \param [in] other - the mesh to compare with.
1796  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1797  *         valid values [0,1,2], see zipConnectivityTraducer().
1798  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1799  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1800  *         values. The caller is to delete this array using
1801  *         decrRef() as it is no more needed.
1802  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1803  *         mesh.
1804  *
1805  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1806  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1807  *  \sa checkDeepEquivalOnSameNodesWith()
1808  *  \sa checkGeoEquivalWith()
1809  */
1810 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1811 {
1812   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1813   int nbOfCells=getNumberOfCells();
1814   static const int possibleCompType[]={0,1,2};
1815   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1816     {
1817       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1818       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1819       oss << " !";
1820       throw INTERP_KERNEL::Exception(oss.str().c_str());
1821     }
1822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1823   arr=o2n->substr(nbOfCells);
1824   arr->setName(other->getName().c_str());
1825   int tmp;
1826   if(other->getNumberOfCells()==0)
1827     return true;
1828   return arr->getMaxValue(tmp)<nbOfCells;
1829 }
1830
1831 /*!
1832  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1833  * This method tries to determine if \b other is fully included in \b this.
1834  * The main difference is that this method is not expected to throw exception.
1835  * This method has two outputs :
1836  *
1837  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1838  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1839  */
1840 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1841 {
1842   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1843   DataArrayInt *commonCells=0,*commonCellsI=0;
1844   int thisNbCells=getNumberOfCells();
1845   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1846   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1847   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1848   int otherNbCells=other->getNumberOfCells();
1849   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1850   arr2->alloc(otherNbCells,1);
1851   arr2->fillWithZero();
1852   int *arr2Ptr=arr2->getPointer();
1853   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1854   for(int i=0;i<nbOfCommon;i++)
1855     {
1856       int start=commonCellsPtr[commonCellsIPtr[i]];
1857       if(start<thisNbCells)
1858         {
1859           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1860             {
1861               int sig=commonCellsPtr[j]>0?1:-1;
1862               int val=std::abs(commonCellsPtr[j])-1;
1863               if(val>=thisNbCells)
1864                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1865             }
1866         }
1867     }
1868   arr2->setName(other->getName().c_str());
1869   if(arr2->presenceOfValue(0))
1870     return false;
1871   arr=arr2.retn();
1872   return true;
1873 }
1874
1875 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1876 {
1877   if(!other)
1878     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1879   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1880   if(!otherC)
1881     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1882   std::vector<const MEDCouplingUMesh *> ms(2);
1883   ms[0]=this;
1884   ms[1]=otherC;
1885   return MergeUMeshesOnSameCoords(ms);
1886 }
1887
1888 /*!
1889  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1890  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1891  * cellIds is not given explicitely but by a range python like.
1892  * 
1893  * \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.
1894  * \return a newly allocated
1895  * 
1896  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1897  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1898  */
1899 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1900 {
1901   if(getMeshDimension()!=-1)
1902     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1903   else
1904     {
1905       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1906       if(newNbOfCells!=1)
1907         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1908       if(start!=0)
1909         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1910       incrRef();
1911       return const_cast<MEDCouplingUMesh *>(this);
1912     }
1913 }
1914
1915 /*!
1916  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1917  * The result mesh shares or not the node coordinates array with \a this mesh depending
1918  * on \a keepCoords parameter.
1919  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1920  *           to write this mesh to the MED file, its cells must be sorted using
1921  *           sortCellsInMEDFileFrmt().
1922  *  \param [in] begin - an array of cell ids to include to the new mesh.
1923  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1924  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1925  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1926  *         by calling zipCoords().
1927  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1928  *         to delete this mesh using decrRef() as it is no more needed. 
1929  *  \throw If the coordinates array is not set.
1930  *  \throw If the nodal connectivity of cells is not defined.
1931  *  \throw If any cell id in the array \a begin is not valid.
1932  *
1933  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1934  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1935  */
1936 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1937 {
1938   if(getMeshDimension()!=-1)
1939     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1940   else
1941     {
1942       if(end-begin!=1)
1943         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1944       if(begin[0]!=0)
1945         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1946       incrRef();
1947       return const_cast<MEDCouplingUMesh *>(this);
1948     }
1949 }
1950
1951 /*!
1952  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1953  *
1954  * 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.
1955  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1956  * The number of cells of \b this will remain the same with this method.
1957  *
1958  * \param [in] begin begin of cell ids (included) of cells in this to assign
1959  * \param [in] end end of cell ids (excluded) of cells in this to assign
1960  * \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 ).
1961  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1962  */
1963 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1964 {
1965   checkConnectivityFullyDefined();
1966   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1967   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1968     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1969   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1970     {
1971       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1972       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1973       throw INTERP_KERNEL::Exception(oss.str().c_str());
1974     }
1975   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1976   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1977     {
1978       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1979       throw INTERP_KERNEL::Exception(oss.str().c_str());
1980     }
1981   int nbOfCells=getNumberOfCells();
1982   bool easyAssign=true;
1983   const int *connI=_nodal_connec_index->getConstPointer();
1984   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1985   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1986     {
1987       if(*it>=0 && *it<nbOfCells)
1988         {
1989           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1990         }
1991       else
1992         {
1993           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1994           throw INTERP_KERNEL::Exception(oss.str().c_str());
1995         }
1996     }
1997   if(easyAssign)
1998     {
1999       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2000       computeTypes();
2001     }
2002   else
2003     {
2004       DataArrayInt *arrOut=0,*arrIOut=0;
2005       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2006                                                arrOut,arrIOut);
2007       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2008       setConnectivity(arrOut,arrIOut,true);
2009     }
2010 }
2011
2012 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2013 {
2014   checkConnectivityFullyDefined();
2015   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2016   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2017     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2018   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2019     {
2020       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2021       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2022       throw INTERP_KERNEL::Exception(oss.str().c_str());
2023     }
2024   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2025   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2026     {
2027       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2028       throw INTERP_KERNEL::Exception(oss.str().c_str());
2029     }
2030   int nbOfCells=getNumberOfCells();
2031   bool easyAssign=true;
2032   const int *connI=_nodal_connec_index->getConstPointer();
2033   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2034   int it=start;
2035   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2036     {
2037       if(it>=0 && it<nbOfCells)
2038         {
2039           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2040         }
2041       else
2042         {
2043           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2044           throw INTERP_KERNEL::Exception(oss.str().c_str());
2045         }
2046     }
2047   if(easyAssign)
2048     {
2049       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2050       computeTypes();
2051     }
2052   else
2053     {
2054       DataArrayInt *arrOut=0,*arrIOut=0;
2055       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2056                                                 arrOut,arrIOut);
2057       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2058       setConnectivity(arrOut,arrIOut,true);
2059     }
2060 }                      
2061
2062 /*!
2063  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2064  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2065  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2066  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2067  *
2068  * \param [in] begin input start of array of node ids.
2069  * \param [in] end input end of array of node ids.
2070  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2071  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2072  */
2073 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2074 {
2075   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2076   checkConnectivityFullyDefined();
2077   int tmp=-1;
2078   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2079   std::vector<bool> fastFinder(sz,false);
2080   for(const int *work=begin;work!=end;work++)
2081     if(*work>=0 && *work<sz)
2082       fastFinder[*work]=true;
2083   int nbOfCells=getNumberOfCells();
2084   const int *conn=getNodalConnectivity()->getConstPointer();
2085   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2086   for(int i=0;i<nbOfCells;i++)
2087     {
2088       int ref=0,nbOfHit=0;
2089       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2090         if(*work2>=0)
2091           {
2092             ref++;
2093             if(fastFinder[*work2])
2094               nbOfHit++;
2095           }
2096       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2097         cellIdsKept->pushBackSilent(i);
2098     }
2099   cellIdsKeptArr=cellIdsKept.retn();
2100 }
2101
2102 /*!
2103  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2104  * this->getMeshDimension(), that bound some cells of \a this mesh.
2105  * The cells of lower dimension to include to the result mesh are selected basing on
2106  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2107  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2108  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2109  * created mesh shares the node coordinates array with \a this mesh. 
2110  *  \param [in] begin - the array of node ids.
2111  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2112  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2113  *         array \a begin are added, else cells whose any node is in the
2114  *         array \a begin are added.
2115  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2116  *         to delete this mesh using decrRef() as it is no more needed. 
2117  *  \throw If the coordinates array is not set.
2118  *  \throw If the nodal connectivity of cells is not defined.
2119  *  \throw If any node id in \a begin is not valid.
2120  *
2121  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2122  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2123  */
2124 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2125 {
2126   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2127   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2128   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2129   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2130   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2131 }
2132
2133 /*!
2134  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2135  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2136  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2137  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2138  *         by calling zipCoords().
2139  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2140  *         to delete this mesh using decrRef() as it is no more needed. 
2141  *  \throw If the coordinates array is not set.
2142  *  \throw If the nodal connectivity of cells is not defined.
2143  *
2144  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2145  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2146  */
2147 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2148 {
2149   DataArrayInt *desc=DataArrayInt::New();
2150   DataArrayInt *descIndx=DataArrayInt::New();
2151   DataArrayInt *revDesc=DataArrayInt::New();
2152   DataArrayInt *revDescIndx=DataArrayInt::New();
2153   //
2154   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2155   revDesc->decrRef();
2156   desc->decrRef();
2157   descIndx->decrRef();
2158   int nbOfCells=meshDM1->getNumberOfCells();
2159   const int *revDescIndxC=revDescIndx->getConstPointer();
2160   std::vector<int> boundaryCells;
2161   for(int i=0;i<nbOfCells;i++)
2162     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2163       boundaryCells.push_back(i);
2164   revDescIndx->decrRef();
2165   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2166   return ret;
2167 }
2168
2169 /*!
2170  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2171  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2172  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2173  */
2174 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2175 {
2176   checkFullyDefined();
2177   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2179   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2180   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2181   //
2182   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2183   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2184   //
2185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2186   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2187   const int *revDescPtr=revDesc->getConstPointer();
2188   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2189   int nbOfCells=getNumberOfCells();
2190   std::vector<bool> ret1(nbOfCells,false);
2191   int sz=0;
2192   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2193     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2194       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2195   //
2196   DataArrayInt *ret2=DataArrayInt::New();
2197   ret2->alloc(sz,1);
2198   int *ret2Ptr=ret2->getPointer();
2199   sz=0;
2200   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2201     if(*it)
2202       *ret2Ptr++=sz;
2203   ret2->setName("BoundaryCells");
2204   return ret2;
2205 }
2206
2207 /*!
2208  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2209  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2210  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2211  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2212  *
2213  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2214  * This method method returns cells ids set s = s1 + s2 where :
2215  * 
2216  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2217  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2218  *
2219  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2220  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2221  *
2222  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2223  * \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
2224  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2225  */
2226 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2227 {
2228   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2229     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2230   checkConnectivityFullyDefined();
2231   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2232   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2233     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2234   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2235   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2236   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2238   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2239   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2240   DataArrayInt *idsOtherInConsti=0;
2241   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2243   if(!b)
2244     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2245   std::set<int> s1;
2246   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2247     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2249   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2250   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2251   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2252   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2253   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2254   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2255   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2256   neighThisPartAuto=0;
2257   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2258   const int li[2]={0,1};
2259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2260   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2261   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2262   s_renum1->sort();
2263   //
2264   cellIdsRk0=s0arr.retn();
2265   cellIdsRk1=s_renum1.retn();
2266 }
2267
2268 /*!
2269  * 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
2270  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2271  * 
2272  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2273  */
2274 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2275 {
2276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2280   //
2281   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2282   revDesc=0; desc=0; descIndx=0;
2283   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2284   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2285   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2286 }
2287
2288 /*!
2289  * Finds nodes lying on the boundary of \a this mesh.
2290  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2291  *          nodes. The caller is to delete this array using decrRef() as it is no
2292  *          more needed.
2293  *  \throw If the coordinates array is not set.
2294  *  \throw If the nodal connectivity of cells is node defined.
2295  *
2296  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2297  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2298  */
2299 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2300 {
2301   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2302   return skin->computeFetchedNodeIds();
2303 }
2304
2305 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2306 {
2307   incrRef();
2308   return const_cast<MEDCouplingUMesh *>(this);
2309 }
2310
2311 /*!
2312  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2313  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2314  * 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.
2315  * 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.
2316  * 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.
2317  *
2318  * \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
2319  *             parameter is altered during the call.
2320  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2321  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2322  * \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.
2323  *
2324  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2325  */
2326 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2327                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2328 {
2329   checkFullyDefined();
2330   otherDimM1OnSameCoords.checkFullyDefined();
2331   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2332     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2333   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2334     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2335   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2336   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2339   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2340   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2341   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2342   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2344   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2345   //
2346   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2348   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2349   DataArrayInt *idsTmp=0;
2350   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2351   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2352   if(!b)
2353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2354   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2355   DataArrayInt *tmp0=0,*tmp1=0;
2356   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2361   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2362   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2363   //
2364   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2365   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2366   nodeIdsToDuplicate=s3.retn();
2367 }
2368
2369 /*!
2370  * This method operates a modification of the connectivity and coords in \b this.
2371  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2372  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2373  * 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
2374  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2375  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2376  * 
2377  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2378  * 
2379  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2380  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2381  */
2382 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2383 {
2384   int nbOfNodes=getNumberOfNodes();
2385   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2386   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2387 }
2388
2389 /*!
2390  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2391  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2392  * This method is a generalization of shiftNodeNumbersInConn().
2393  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2394  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2395  *         this->getNumberOfNodes(), in "Old to New" mode. 
2396  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2397  *  \throw If the nodal connectivity of cells is not defined.
2398  *
2399  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2400  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2401  */
2402 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2403 {
2404   checkConnectivityFullyDefined();
2405   int *conn=getNodalConnectivity()->getPointer();
2406   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2407   int nbOfCells=getNumberOfCells();
2408   for(int i=0;i<nbOfCells;i++)
2409     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2410       {
2411         int& node=conn[iconn];
2412         if(node>=0)//avoid polyhedron separator
2413           {
2414             node=newNodeNumbersO2N[node];
2415           }
2416       }
2417   _nodal_connec->declareAsNew();
2418   updateTime();
2419 }
2420
2421 /*!
2422  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2423  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2424  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2425  * 
2426  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2427  */
2428 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2429 {
2430   checkConnectivityFullyDefined();
2431   int *conn=getNodalConnectivity()->getPointer();
2432   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2433   int nbOfCells=getNumberOfCells();
2434   for(int i=0;i<nbOfCells;i++)
2435     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2436       {
2437         int& node=conn[iconn];
2438         if(node>=0)//avoid polyhedron separator
2439           {
2440             node+=delta;
2441           }
2442       }
2443   _nodal_connec->declareAsNew();
2444   updateTime();
2445 }
2446
2447 /*!
2448  * This method operates a modification of the connectivity in \b this.
2449  * 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.
2450  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2451  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2452  * 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
2453  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2454  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2455  * 
2456  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2457  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2458  * 
2459  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2460  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2461  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2462  */
2463 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2464 {
2465   checkConnectivityFullyDefined();
2466   std::map<int,int> m;
2467   int val=offset;
2468   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2469     m[*work]=val;
2470   int *conn=getNodalConnectivity()->getPointer();
2471   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2472   int nbOfCells=getNumberOfCells();
2473   for(int i=0;i<nbOfCells;i++)
2474     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2475       {
2476         int& node=conn[iconn];
2477         if(node>=0)//avoid polyhedron separator
2478           {
2479             std::map<int,int>::iterator it=m.find(node);
2480             if(it!=m.end())
2481               node=(*it).second;
2482           }
2483       }
2484   updateTime();
2485 }
2486
2487 /*!
2488  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2489  *
2490  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2491  * After the call of this method the number of cells remains the same as before.
2492  *
2493  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2494  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2495  * be strictly in [0;this->getNumberOfCells()).
2496  *
2497  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2498  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2499  * should be contained in[0;this->getNumberOfCells()).
2500  * 
2501  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2502  */
2503 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2504 {
2505   checkConnectivityFullyDefined();
2506   int nbCells=getNumberOfCells();
2507   const int *array=old2NewBg;
2508   if(check)
2509     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2510   //
2511   const int *conn=_nodal_connec->getConstPointer();
2512   const int *connI=_nodal_connec_index->getConstPointer();
2513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2515   const int *n2oPtr=n2o->begin();
2516   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2517   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2518   newConn->copyStringInfoFrom(*_nodal_connec);
2519   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2520   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2521   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2522   //
2523   int *newC=newConn->getPointer();
2524   int *newCI=newConnI->getPointer();
2525   int loc=0;
2526   newCI[0]=loc;
2527   for(int i=0;i<nbCells;i++)
2528     {
2529       int pos=n2oPtr[i];
2530       int nbOfElts=connI[pos+1]-connI[pos];
2531       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2532       loc+=nbOfElts;
2533       newCI[i+1]=loc;
2534     }
2535   //
2536   setConnectivity(newConn,newConnI);
2537   if(check)
2538     free(const_cast<int *>(array));
2539 }
2540
2541 /*!
2542  * Finds cells whose bounding boxes intersect a given bounding box.
2543  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2544  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2545  *         zMax (if in 3D). 
2546  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2547  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2548  *         extent of the bounding box of cell to produce an addition to this bounding box.
2549  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2550  *         cells. The caller is to delete this array using decrRef() as it is no more
2551  *         needed. 
2552  *  \throw If the coordinates array is not set.
2553  *  \throw If the nodal connectivity of cells is not defined.
2554  *
2555  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2556  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2557  */
2558 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2559 {
2560   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2561   if(getMeshDimension()==-1)
2562     {
2563       elems->pushBackSilent(0);
2564       return elems.retn();
2565     }
2566   int dim=getSpaceDimension();
2567   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2568   const int* conn      = getNodalConnectivity()->getConstPointer();
2569   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2570   const double* coords = getCoords()->getConstPointer();
2571   int nbOfCells=getNumberOfCells();
2572   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2573     {
2574       for (int i=0; i<dim; i++)
2575         {
2576           elem_bb[i*2]=std::numeric_limits<double>::max();
2577           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2578         }
2579
2580       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2581         {
2582           int node= conn[inode];
2583           if(node>=0)//avoid polyhedron separator
2584             {
2585               for (int idim=0; idim<dim; idim++)
2586                 {
2587                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2588                     {
2589                       elem_bb[idim*2] = coords[node*dim+idim] ;
2590                     }
2591                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2592                     {
2593                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2594                     }
2595                 }
2596             }
2597         }
2598       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2599         elems->pushBackSilent(ielem);
2600     }
2601   return elems.retn();
2602 }
2603
2604 /*!
2605  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2606  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2607  * added in 'elems' parameter.
2608  */
2609 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2610 {
2611   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2612   if(getMeshDimension()==-1)
2613     {
2614       elems->pushBackSilent(0);
2615       return elems.retn();
2616     }
2617   int dim=getSpaceDimension();
2618   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2619   const int* conn      = getNodalConnectivity()->getConstPointer();
2620   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2621   const double* coords = getCoords()->getConstPointer();
2622   int nbOfCells=getNumberOfCells();
2623   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2624     {
2625       for (int i=0; i<dim; i++)
2626         {
2627           elem_bb[i*2]=std::numeric_limits<double>::max();
2628           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2629         }
2630
2631       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2632         {
2633           int node= conn[inode];
2634           if(node>=0)//avoid polyhedron separator
2635             {
2636               for (int idim=0; idim<dim; idim++)
2637                 {
2638                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2639                     {
2640                       elem_bb[idim*2] = coords[node*dim+idim] ;
2641                     }
2642                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2643                     {
2644                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2645                     }
2646                 }
2647             }
2648         }
2649       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2650         elems->pushBackSilent(ielem);
2651     }
2652   return elems.retn();
2653 }
2654
2655 /*!
2656  * Returns a type of a cell by its id.
2657  *  \param [in] cellId - the id of the cell of interest.
2658  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2659  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2660  */
2661 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2662 {
2663   const int *ptI=_nodal_connec_index->getConstPointer();
2664   const int *pt=_nodal_connec->getConstPointer();
2665   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2666     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2667   else
2668     {
2669       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2670       throw INTERP_KERNEL::Exception(oss.str().c_str());
2671     }
2672 }
2673
2674 /*!
2675  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2676  * This method does not throw exception if geometric type \a type is not in \a this.
2677  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2678  * The coordinates array is not considered here.
2679  *
2680  * \param [in] type the geometric type
2681  * \return cell ids in this having geometric type \a type.
2682  */
2683 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2684 {
2685   
2686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2687   ret->alloc(0,1);
2688   checkConnectivityFullyDefined();
2689   int nbCells=getNumberOfCells();
2690   int mdim=getMeshDimension();
2691   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2692   if(mdim!=(int)cm.getDimension())
2693     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2694   const int *ptI=_nodal_connec_index->getConstPointer();
2695   const int *pt=_nodal_connec->getConstPointer();
2696   for(int i=0;i<nbCells;i++)
2697     {
2698       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2699         ret->pushBackSilent(i);
2700     }
2701   return ret.retn();
2702 }
2703
2704 /*!
2705  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2706  */
2707 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2708 {
2709   const int *ptI=_nodal_connec_index->getConstPointer();
2710   const int *pt=_nodal_connec->getConstPointer();
2711   int nbOfCells=getNumberOfCells();
2712   int ret=0;
2713   for(int i=0;i<nbOfCells;i++)
2714     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2715       ret++;
2716   return ret;
2717 }
2718
2719 /*!
2720  * Returns the nodal connectivity of a given cell.
2721  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2722  * all returned node ids can be used in getCoordinatesOfNode().
2723  *  \param [in] cellId - an id of the cell of interest.
2724  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2725  *         cleared before the appending.
2726  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2727  */
2728 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2729 {
2730   const int *ptI=_nodal_connec_index->getConstPointer();
2731   const int *pt=_nodal_connec->getConstPointer();
2732   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2733     if(*w>=0)
2734       conn.push_back(*w);
2735 }
2736
2737 std::string MEDCouplingUMesh::simpleRepr() const
2738 {
2739   static const char msg0[]="No coordinates specified !";
2740   std::ostringstream ret;
2741   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2742   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2743   int tmpp1,tmpp2;
2744   double tt=getTime(tmpp1,tmpp2);
2745   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2746   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2747   if(_mesh_dim>=-1)
2748     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2749   else
2750     { ret << " Mesh dimension has not been set or is invalid !"; }
2751   if(_coords!=0)
2752     {
2753       const int spaceDim=getSpaceDimension();
2754       ret << spaceDim << "\nInfo attached on space dimension : ";
2755       for(int i=0;i<spaceDim;i++)
2756         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2757       ret << "\n";
2758     }
2759   else
2760     ret << msg0 << "\n";
2761   ret << "Number of nodes : ";
2762   if(_coords!=0)
2763     ret << getNumberOfNodes() << "\n";
2764   else
2765     ret << msg0 << "\n";
2766   ret << "Number of cells : ";
2767   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2768     ret << getNumberOfCells() << "\n";
2769   else
2770     ret << "No connectivity specified !" << "\n";
2771   ret << "Cell types present : ";
2772   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2773     {
2774       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2775       ret << cm.getRepr() << " ";
2776     }
2777   ret << "\n";
2778   return ret.str();
2779 }
2780
2781 std::string MEDCouplingUMesh::advancedRepr() const
2782 {
2783   std::ostringstream ret;
2784   ret << simpleRepr();
2785   ret << "\nCoordinates array : \n___________________\n\n";
2786   if(_coords)
2787     _coords->reprWithoutNameStream(ret);
2788   else
2789     ret << "No array set !\n";
2790   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2791   reprConnectivityOfThisLL(ret);
2792   return ret.str();
2793 }
2794
2795 /*!
2796  * This method returns a C++ code that is a dump of \a this.
2797  * This method will throw if this is not fully defined.
2798  */
2799 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2800 {
2801   static const char coordsName[]="coords";
2802   static const char connName[]="conn";
2803   static const char connIName[]="connI";
2804   checkFullyDefined();
2805   std::ostringstream ret; ret << "// coordinates" << std::endl;
2806   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2807   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2808   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2809   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2810   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2811   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2812   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2813   return ret.str();
2814 }
2815
2816 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2817 {
2818   std::ostringstream ret;
2819   reprConnectivityOfThisLL(ret);
2820   return ret.str();
2821 }
2822
2823 /*!
2824  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2825  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2826  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2827  * some algos).
2828  * 
2829  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2830  * 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
2831  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2832  */
2833 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2834 {
2835   int mdim=getMeshDimension();
2836   if(mdim<0)
2837     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2838   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
2839   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2840   bool needToCpyCT=true;
2841   if(!_nodal_connec)
2842     {
2843       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2844       needToCpyCT=false;
2845     }
2846   else
2847     {
2848       tmp1=_nodal_connec;
2849       tmp1->incrRef();
2850     }
2851   if(!_nodal_connec_index)
2852     {
2853       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2854       needToCpyCT=false;
2855     }
2856   else
2857     {
2858       tmp2=_nodal_connec_index;
2859       tmp2->incrRef();
2860     }
2861   ret->setConnectivity(tmp1,tmp2,false);
2862   if(needToCpyCT)
2863     ret->_types=_types;
2864   if(!_coords)
2865     {
2866       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2867       ret->setCoords(coords);
2868     }
2869   else
2870     ret->setCoords(_coords);
2871   return ret.retn();
2872 }
2873
2874 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2875 {
2876   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2877     {
2878       int nbOfCells=getNumberOfCells();
2879       const int *c=_nodal_connec->getConstPointer();
2880       const int *ci=_nodal_connec_index->getConstPointer();
2881       for(int i=0;i<nbOfCells;i++)
2882         {
2883           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2884           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2885           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2886           stream << "\n";
2887         }
2888     }
2889   else
2890     stream << "Connectivity not defined !\n";
2891 }
2892
2893 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2894 {
2895   const int *ptI=_nodal_connec_index->getConstPointer();
2896   const int *pt=_nodal_connec->getConstPointer();
2897   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2898     return ptI[cellId+1]-ptI[cellId]-1;
2899   else
2900     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2901 }
2902
2903 /*!
2904  * Returns types of cells of the specified part of \a this mesh.
2905  * This method avoids computing sub-mesh explicitely to get its types.
2906  *  \param [in] begin - an array of cell ids of interest.
2907  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2908  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2909  *         describing the cell types. 
2910  *  \throw If the coordinates array is not set.
2911  *  \throw If the nodal connectivity of cells is not defined.
2912  *  \sa getAllTypes()
2913  */
2914 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2915 {
2916   checkFullyDefined();
2917   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2918   const int *conn=_nodal_connec->getConstPointer();
2919   const int *connIndex=_nodal_connec_index->getConstPointer();
2920   for(const int *w=begin;w!=end;w++)
2921     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2922   return ret;
2923 }
2924
2925 /*!
2926  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2927  * a set of types of cells constituting \a this mesh. 
2928  * This method is for advanced users having prepared their connectivity before. For
2929  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2930  *  \param [in] conn - the nodal connectivity array. 
2931  *  \param [in] connIndex - the nodal connectivity index array.
2932  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2933  *         mesh is updated.
2934  */
2935 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2936 {
2937   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2938   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2939   if(isComputingTypes)
2940     computeTypes();
2941   declareAsNew();
2942 }
2943
2944 /*!
2945  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2946  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2947  */
2948 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2949                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2950                                                                                 _types(other._types)
2951 {
2952   if(other._nodal_connec)
2953     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2954   if(other._nodal_connec_index)
2955     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2956 }
2957
2958 MEDCouplingUMesh::~MEDCouplingUMesh()
2959 {
2960   if(_nodal_connec)
2961     _nodal_connec->decrRef();
2962   if(_nodal_connec_index)
2963     _nodal_connec_index->decrRef();
2964 }
2965
2966 /*!
2967  * Recomputes a set of cell types of \a this mesh. For more info see
2968  * \ref MEDCouplingUMeshNodalConnectivity.
2969  */
2970 void MEDCouplingUMesh::computeTypes()
2971 {
2972   if(_nodal_connec && _nodal_connec_index)
2973     {
2974       _types.clear();
2975       const int *conn=_nodal_connec->getConstPointer();
2976       const int *connIndex=_nodal_connec_index->getConstPointer();
2977       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2978       if (nbOfElem > 0)
2979         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2980           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2981     }
2982 }
2983
2984 /*!
2985  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2986  */
2987 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2988 {
2989   if(!_nodal_connec_index || !_nodal_connec || !_coords)
2990     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2991 }
2992
2993 /*!
2994  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2995  */
2996 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2997 {
2998   if(!_nodal_connec_index || !_nodal_connec)
2999     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3000 }
3001
3002 /*!
3003  * Returns a number of cells constituting \a this mesh. 
3004  *  \return int - the number of cells in \a this mesh.
3005  *  \throw If the nodal connectivity of cells is not defined.
3006  */
3007 int MEDCouplingUMesh::getNumberOfCells() const
3008
3009   if(_nodal_connec_index)
3010     return _nodal_connec_index->getNumberOfTuples()-1;
3011   else
3012     if(_mesh_dim==-1)
3013       return 1;
3014     else
3015       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3016 }
3017
3018 /*!
3019  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3020  * mesh. For more info see \ref MEDCouplingMeshesPage.
3021  *  \return int - the dimension of \a this mesh.
3022  *  \throw If the mesh dimension is not defined using setMeshDimension().
3023  */
3024 int MEDCouplingUMesh::getMeshDimension() const
3025 {
3026   if(_mesh_dim<-1)
3027     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3028   return _mesh_dim;
3029 }
3030
3031 /*!
3032  * Returns a length of the nodal connectivity array.
3033  * This method is for test reason. Normally the integer returned is not useable by
3034  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3035  *  \return int - the length of the nodal connectivity array.
3036  */
3037 int MEDCouplingUMesh::getMeshLength() const
3038 {
3039   return _nodal_connec->getNbOfElems();
3040 }
3041
3042 /*!
3043  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3044  */
3045 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3046 {
3047   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3048   tinyInfo.push_back(getMeshDimension());
3049   tinyInfo.push_back(getNumberOfCells());
3050   if(_nodal_connec)
3051     tinyInfo.push_back(getMeshLength());
3052   else
3053     tinyInfo.push_back(-1);
3054 }
3055
3056 /*!
3057  * First step of unserialization process.
3058  */
3059 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3060 {
3061   return tinyInfo[6]<=0;
3062 }
3063
3064 /*!
3065  * Second step of serialization process.
3066  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3067  */
3068 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3069 {
3070   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3071   if(tinyInfo[5]!=-1)
3072     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3073 }
3074
3075 /*!
3076  * Third and final step of serialization process.
3077  */
3078 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3079 {
3080   MEDCouplingPointSet::serialize(a1,a2);
3081   if(getMeshDimension()>-1)
3082     {
3083       a1=DataArrayInt::New();
3084       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3085       int *ptA1=a1->getPointer();
3086       const int *conn=getNodalConnectivity()->getConstPointer();
3087       const int *index=getNodalConnectivityIndex()->getConstPointer();
3088       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3089       std::copy(conn,conn+getMeshLength(),ptA1);
3090     }
3091   else
3092     a1=0;
3093 }
3094
3095 /*!
3096  * Second and final unserialization process.
3097  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3098  */
3099 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3100 {
3101   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3102   setMeshDimension(tinyInfo[5]);
3103   if(tinyInfo[7]!=-1)
3104     {
3105       // Connectivity
3106       const int *recvBuffer=a1->getConstPointer();
3107       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3108       myConnecIndex->alloc(tinyInfo[6]+1,1);
3109       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3110       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3111       myConnec->alloc(tinyInfo[7],1);
3112       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3113       setConnectivity(myConnec, myConnecIndex);
3114     }
3115 }
3116
3117 /*!
3118  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3119  * CellIds are given using range specified by a start an end and step.
3120  */
3121 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3122 {
3123   checkFullyDefined();
3124   int ncell=getNumberOfCells();
3125   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3126   ret->_mesh_dim=_mesh_dim;
3127   ret->setCoords(_coords);
3128   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3129   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3130   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3131   int work=start;
3132   const int *conn=_nodal_connec->getConstPointer();
3133   const int *connIndex=_nodal_connec_index->getConstPointer();
3134   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3135     {
3136       if(work>=0 && work<ncell)
3137         {
3138           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3139         }
3140       else
3141         {
3142           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3143           throw INTERP_KERNEL::Exception(oss.str().c_str());
3144         }
3145     }
3146   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3147   int *newConnPtr=newConn->getPointer();
3148   std::set<INTERP_KERNEL::NormalizedCellType> types;
3149   work=start;
3150   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3151     {
3152       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3153       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3154     }
3155   ret->setConnectivity(newConn,newConnI,false);
3156   ret->_types=types;
3157   ret->copyTinyInfoFrom(this);
3158   return ret.retn();
3159 }
3160
3161 /*!
3162  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3163  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3164  * The return newly allocated mesh will share the same coordinates as \a this.
3165  */
3166 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3167 {
3168   checkConnectivityFullyDefined();
3169   int ncell=getNumberOfCells();
3170   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3171   ret->_mesh_dim=_mesh_dim;
3172   ret->setCoords(_coords);
3173   std::size_t nbOfElemsRet=std::distance(begin,end);
3174   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3175   connIndexRet[0]=0;
3176   const int *conn=_nodal_connec->getConstPointer();
3177   const int *connIndex=_nodal_connec_index->getConstPointer();
3178   int newNbring=0;
3179   for(const int *work=begin;work!=end;work++,newNbring++)
3180     {
3181       if(*work>=0 && *work<ncell)
3182         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3183       else
3184         {
3185           free(connIndexRet);
3186           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3187           throw INTERP_KERNEL::Exception(oss.str().c_str());
3188         }
3189     }
3190   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3191   int *connRetWork=connRet;
3192   std::set<INTERP_KERNEL::NormalizedCellType> types;
3193   for(const int *work=begin;work!=end;work++)
3194     {
3195       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3196       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3197     }
3198   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3199   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3200   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3201   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3202   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3203   ret->_types=types;
3204   ret->copyTinyInfoFrom(this);
3205   return ret.retn();
3206 }
3207
3208 /*!
3209  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3210  * mesh.<br>
3211  * For 1D cells, the returned field contains lengths.<br>
3212  * For 2D cells, the returned field contains areas.<br>
3213  * For 3D cells, the returned field contains volumes.
3214  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3215  *         orientation, i.e. the volume is always positive.
3216  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3217  *         and one time . The caller is to delete this field using decrRef() as it is no
3218  *         more needed.
3219  */
3220 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3221 {
3222   std::string name="MeasureOfMesh_";
3223   name+=getName();
3224   int nbelem=getNumberOfCells();
3225   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3226   field->setName(name.c_str());
3227   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3228   array->alloc(nbelem,1);
3229   double *area_vol=array->getPointer();
3230   field->setArray(array) ; array=0;
3231   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3232   field->synchronizeTimeWithMesh();
3233   if(getMeshDimension()!=-1)
3234     {
3235       int ipt;
3236       INTERP_KERNEL::NormalizedCellType type;
3237       int dim_space=getSpaceDimension();
3238       const double *coords=getCoords()->getConstPointer();
3239       const int *connec=getNodalConnectivity()->getConstPointer();
3240       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3241       for(int iel=0;iel<nbelem;iel++)
3242         {
3243           ipt=connec_index[iel];
3244           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3245           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);
3246         }
3247       if(isAbs)
3248         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3249     }
3250   else
3251     {
3252       area_vol[0]=std::numeric_limits<double>::max();
3253     }
3254   return field.retn();
3255 }
3256
3257 /*!
3258  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3259  * mesh.<br>
3260  * For 1D cells, the returned array contains lengths.<br>
3261  * For 2D cells, the returned array contains areas.<br>
3262  * For 3D cells, the returned array contains volumes.
3263  * This method avoids building explicitly a part of \a this mesh to perform the work.
3264  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3265  *         orientation, i.e. the volume is always positive.
3266  *  \param [in] begin - an array of cell ids of interest.
3267  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3268  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3269  *          delete this array using decrRef() as it is no more needed.
3270  * 
3271  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3272  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3273  *  \sa getMeasureField()
3274  */
3275 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3276 {
3277   std::string name="PartMeasureOfMesh_";
3278   name+=getName();
3279   int nbelem=(int)std::distance(begin,end);
3280   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3281   array->setName(name.c_str());
3282   array->alloc(nbelem,1);
3283   double *area_vol=array->getPointer();
3284   if(getMeshDimension()!=-1)
3285     {
3286       int ipt;
3287       INTERP_KERNEL::NormalizedCellType type;
3288       int dim_space=getSpaceDimension();
3289       const double *coords=getCoords()->getConstPointer();
3290       const int *connec=getNodalConnectivity()->getConstPointer();
3291       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3292       for(const int *iel=begin;iel!=end;iel++)
3293         {
3294           ipt=connec_index[*iel];
3295           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3296           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3297         }
3298       if(isAbs)
3299         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3300     }
3301   else
3302     {
3303       area_vol[0]=std::numeric_limits<double>::max();
3304     }
3305   return array.retn();
3306 }
3307
3308 /*!
3309  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3310  * \a this one. The returned field contains the dual cell volume for each corresponding
3311  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3312  *  the dual mesh in P1 sens of \a this.<br>
3313  * For 1D cells, the returned field contains lengths.<br>
3314  * For 2D cells, the returned field contains areas.<br>
3315  * For 3D cells, the returned field contains volumes.
3316  * This method is useful to check "P1*" conservative interpolators.
3317  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3318  *         orientation, i.e. the volume is always positive.
3319  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3320  *          nodes and one time. The caller is to delete this array using decrRef() as
3321  *          it is no more needed.
3322  */
3323 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3324 {
3325   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3326   std::string name="MeasureOnNodeOfMesh_";
3327   name+=getName();
3328   int nbNodes=getNumberOfNodes();
3329   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3330   double cst=1./((double)getMeshDimension()+1.);
3331   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3332   array->alloc(nbNodes,1);
3333   double *valsToFill=array->getPointer();
3334   std::fill(valsToFill,valsToFill+nbNodes,0.);
3335   const double *values=tmp->getArray()->getConstPointer();
3336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3338   getReverseNodalConnectivity(da,daInd);
3339   const int *daPtr=da->getConstPointer();
3340   const int *daIPtr=daInd->getConstPointer();
3341   for(int i=0;i<nbNodes;i++)
3342     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3343       valsToFill[i]+=cst*values[*cell];
3344   ret->setMesh(this);
3345   ret->setArray(array);
3346   return ret.retn();
3347 }
3348
3349 /*!
3350  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3351  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3352  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3353  * and are normalized.
3354  * <br> \a this can be either 
3355  * - a  2D mesh in 2D or 3D space or 
3356  * - an 1D mesh in 2D space.
3357  * 
3358  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3359  *          cells and one time. The caller is to delete this field using decrRef() as
3360  *          it is no more needed.
3361  *  \throw If the nodal connectivity of cells is not defined.
3362  *  \throw If the coordinates array is not set.
3363  *  \throw If the mesh dimension is not set.
3364  *  \throw If the mesh and space dimension is not as specified above.
3365  */
3366 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3367 {
3368   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3369     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3370   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3371   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3372   int nbOfCells=getNumberOfCells();
3373   int nbComp=getMeshDimension()+1;
3374   array->alloc(nbOfCells,nbComp);
3375   double *vals=array->getPointer();
3376   const int *connI=_nodal_connec_index->getConstPointer();
3377   const int *conn=_nodal_connec->getConstPointer();
3378   const double *coords=_coords->getConstPointer();
3379   if(getMeshDimension()==2)
3380     {
3381       if(getSpaceDimension()==3)
3382         {
3383           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3384           const double *locPtr=loc->getConstPointer();
3385           for(int i=0;i<nbOfCells;i++,vals+=3)
3386             {
3387               int offset=connI[i];
3388               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3389               double n=INTERP_KERNEL::norm<3>(vals);
3390               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3391             }
3392         }
3393       else
3394         {
3395           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3396           const double *isAbsPtr=isAbs->getArray()->begin();
3397           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3398             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3399         }
3400     }
3401   else//meshdimension==1
3402     {
3403       double tmp[2];
3404       for(int i=0;i<nbOfCells;i++)
3405         {
3406           int offset=connI[i];
3407           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3408           double n=INTERP_KERNEL::norm<2>(tmp);
3409           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3410           *vals++=-tmp[1];
3411           *vals++=tmp[0];
3412         }
3413     }
3414   ret->setArray(array);
3415   ret->setMesh(this);
3416   ret->synchronizeTimeWithSupport();
3417   return ret.retn();
3418 }
3419
3420 /*!
3421  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3422  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3423  * and are normalized.
3424  * <br> \a this can be either 
3425  * - a  2D mesh in 2D or 3D space or 
3426  * - an 1D mesh in 2D space.
3427  * 
3428  * This method avoids building explicitly a part of \a this mesh to perform the work.
3429  *  \param [in] begin - an array of cell ids of interest.
3430  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3431  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3432  *          cells and one time. The caller is to delete this field using decrRef() as
3433  *          it is no more needed.
3434  *  \throw If the nodal connectivity of cells is not defined.
3435  *  \throw If the coordinates array is not set.
3436  *  \throw If the mesh dimension is not set.
3437  *  \throw If the mesh and space dimension is not as specified above.
3438  *  \sa buildOrthogonalField()
3439  *
3440  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3441  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3442  */
3443 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3444 {
3445   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3446     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3447   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3448   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3449   std::size_t nbelems=std::distance(begin,end);
3450   int nbComp=getMeshDimension()+1;
3451   array->alloc((int)nbelems,nbComp);
3452   double *vals=array->getPointer();
3453   const int *connI=_nodal_connec_index->getConstPointer();
3454   const int *conn=_nodal_connec->getConstPointer();
3455   const double *coords=_coords->getConstPointer();
3456   if(getMeshDimension()==2)
3457     {
3458       if(getSpaceDimension()==3)
3459         {
3460           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3461           const double *locPtr=loc->getConstPointer();
3462           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3463             {
3464               int offset=connI[*i];
3465               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3466               double n=INTERP_KERNEL::norm<3>(vals);
3467               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3468             }
3469         }
3470       else
3471         {
3472           for(std::size_t i=0;i<nbelems;i++)
3473             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3474         }
3475     }
3476   else//meshdimension==1
3477     {
3478       double tmp[2];
3479       for(const int *i=begin;i!=end;i++)
3480         {
3481           int offset=connI[*i];
3482           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3483           double n=INTERP_KERNEL::norm<2>(tmp);
3484           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3485           *vals++=-tmp[1];
3486           *vals++=tmp[0];
3487         }
3488     }
3489   ret->setArray(array);
3490   ret->setMesh(this);
3491   ret->synchronizeTimeWithSupport();
3492   return ret.retn();
3493 }
3494
3495 /*!
3496  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3497  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3498  * and are \b not normalized.
3499  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3500  *          cells and one time. The caller is to delete this field using decrRef() as
3501  *          it is no more needed.
3502  *  \throw If the nodal connectivity of cells is not defined.
3503  *  \throw If the coordinates array is not set.
3504  *  \throw If \a this->getMeshDimension() != 1.
3505  *  \throw If \a this mesh includes cells of type other than SEG2.
3506  */
3507 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3508 {
3509    if(getMeshDimension()!=1)
3510     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3511    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3512      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3513    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3514    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3515    int nbOfCells=getNumberOfCells();
3516    int spaceDim=getSpaceDimension();
3517    array->alloc(nbOfCells,spaceDim);
3518    double *pt=array->getPointer();
3519    const double *coo=getCoords()->getConstPointer();
3520    std::vector<int> conn;
3521    conn.reserve(2);
3522    for(int i=0;i<nbOfCells;i++)
3523      {
3524        conn.resize(0);
3525        getNodeIdsOfCell(i,conn);
3526        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3527      }
3528    ret->setArray(array);
3529    ret->setMesh(this);
3530    ret->synchronizeTimeWithSupport();
3531    return ret.retn();   
3532 }
3533
3534 /*!
3535  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3536  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3537  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3538  * from. If a result face is shared by two 3D cells, then the face in included twice in
3539  * the result mesh.
3540  *  \param [in] origin - 3 components of a point defining location of the plane.
3541  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3542  *         must be greater than 1e-6.
3543  *  \param [in] eps - half-thickness of the plane.
3544  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3545  *         producing correspondent 2D cells. The caller is to delete this array
3546  *         using decrRef() as it is no more needed.
3547  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3548  *         not share the node coordinates array with \a this mesh. The caller is to
3549  *         delete this mesh using decrRef() as it is no more needed.  
3550  *  \throw If the coordinates array is not set.
3551  *  \throw If the nodal connectivity of cells is not defined.
3552  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3553  *  \throw If magnitude of \a vec is less than 1e-6.
3554  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3555  *  \throw If \a this includes quadratic cells.
3556  */
3557 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3558 {
3559   checkFullyDefined();
3560   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3561     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3562   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3563   if(candidates->empty())
3564     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3565   std::vector<int> nodes;
3566   DataArrayInt *cellIds1D=0;
3567   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3568   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3569   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3570   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3571   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3572   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3573   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3574   revDesc2=0; revDescIndx2=0;
3575   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3576   revDesc1=0; revDescIndx1=0;
3577   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3578   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3579   //
3580   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3581   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3582     cut3DCurve[*it]=-1;
3583   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3584   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3585   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3586                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3587                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3588   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3589   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3590   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3591   if(cellIds2->empty())
3592     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3593   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3594   ret->setCoords(mDesc1->getCoords());
3595   ret->setConnectivity(conn,connI,true);
3596   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3597   return ret.retn();
3598 }
3599
3600 /*!
3601  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3602 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
3603 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3604 the result mesh.
3605  *  \param [in] origin - 3 components of a point defining location of the plane.
3606  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3607  *         must be greater than 1e-6.
3608  *  \param [in] eps - half-thickness of the plane.
3609  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3610  *         producing correspondent segments. The caller is to delete this array
3611  *         using decrRef() as it is no more needed.
3612  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3613  *         mesh in 3D space. This mesh does not share the node coordinates array with
3614  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3615  *         no more needed. 
3616  *  \throw If the coordinates array is not set.
3617  *  \throw If the nodal connectivity of cells is not defined.
3618  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3619  *  \throw If magnitude of \a vec is less than 1e-6.
3620  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3621  *  \throw If \a this includes quadratic cells.
3622  */
3623 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3624 {
3625   checkFullyDefined();
3626   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3627     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3628   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3629   if(candidates->empty())
3630     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3631   std::vector<int> nodes;
3632   DataArrayInt *cellIds1D=0;
3633   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3634   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3635   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3637   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3639   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3640   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3641   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3642   //
3643   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3644   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3645     cut3DCurve[*it]=-1;
3646   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3647   int ncellsSub=subMesh->getNumberOfCells();
3648   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3649   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3650                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3651                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3652   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3653   conn->alloc(0,1);
3654   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3655   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3656   for(int i=0;i<ncellsSub;i++)
3657     {
3658       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3659         {
3660           if(cut3DSurf[i].first!=-2)
3661             {
3662               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3663               connI->pushBackSilent(conn->getNumberOfTuples());
3664               cellIds2->pushBackSilent(i);
3665             }
3666           else
3667             {
3668               int cellId3DSurf=cut3DSurf[i].second;
3669               int offset=nodalI[cellId3DSurf]+1;
3670               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3671               for(int j=0;j<nbOfEdges;j++)
3672                 {
3673                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3674                   connI->pushBackSilent(conn->getNumberOfTuples());
3675                   cellIds2->pushBackSilent(cellId3DSurf);
3676                 }
3677             }
3678         }
3679     }
3680   if(cellIds2->empty())
3681     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3682   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3683   ret->setCoords(mDesc1->getCoords());
3684   ret->setConnectivity(conn,connI,true);
3685   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3686   return ret.retn();
3687 }
3688
3689 /*!
3690  * Finds cells whose bounding boxes intersect a given plane.
3691  *  \param [in] origin - 3 components of a point defining location of the plane.
3692  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3693  *         must be greater than 1e-6.
3694  *  \param [in] eps - half-thickness of the plane.
3695  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3696  *         cells. The caller is to delete this array using decrRef() as it is no more
3697  *         needed.
3698  *  \throw If the coordinates array is not set.
3699  *  \throw If the nodal connectivity of cells is not defined.
3700  *  \throw If \a this->getSpaceDimension() != 3.
3701  *  \throw If magnitude of \a vec is less than 1e-6.
3702  *  \sa buildSlice3D()
3703  */
3704 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3705 {
3706   checkFullyDefined();
3707   if(getSpaceDimension()!=3)
3708     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3709   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3710   if(normm<1e-6)
3711     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3712   double vec2[3];
3713   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3714   double angle=acos(vec[2]/normm);
3715   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3716   double bbox[6];
3717   if(angle>eps)
3718     {
3719       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3720       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3721       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3722       mw->setCoords(coo);
3723       mw->getBoundingBox(bbox);
3724       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3725       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3726     }
3727   else
3728     {
3729       getBoundingBox(bbox);
3730       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3731       cellIds=getCellsInBoundingBox(bbox,eps);
3732     }
3733   return cellIds.retn();
3734 }
3735
3736 /*!
3737  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3738  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3739  * No consideration of coordinate is done by this method.
3740  * 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)
3741  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3742  */
3743 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3744 {
3745   if(getMeshDimension()!=1)
3746     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3747   int nbCells=getNumberOfCells();
3748   if(nbCells<1)
3749     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3750   const int *connI=_nodal_connec_index->getConstPointer();
3751   const int *conn=_nodal_connec->getConstPointer();
3752   int ref=conn[connI[0]+2];
3753   for(int i=1;i<nbCells;i++)
3754     {
3755       if(conn[connI[i]+1]!=ref)
3756         return false;
3757       ref=conn[connI[i]+2];
3758     }
3759   return true;
3760 }
3761
3762 /*!
3763  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3764  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3765  * \param pt reference point of the line
3766  * \param v normalized director vector of the line
3767  * \param eps max precision before throwing an exception
3768  * \param res output of size this->getNumberOfCells
3769  */
3770 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3771 {
3772   if(getMeshDimension()!=1)
3773     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3774    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3775      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3776    if(getSpaceDimension()!=3)
3777      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3778    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3779    const double *fPtr=f->getArray()->getConstPointer();
3780    double tmp[3];
3781    for(int i=0;i<getNumberOfCells();i++)
3782      {
3783        const double *tmp1=fPtr+3*i;
3784        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3785        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3786        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3787        double n1=INTERP_KERNEL::norm<3>(tmp);
3788        n1/=INTERP_KERNEL::norm<3>(tmp1);
3789        if(n1>eps)
3790          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3791      }
3792    const double *coo=getCoords()->getConstPointer();
3793    for(int i=0;i<getNumberOfNodes();i++)
3794      {
3795        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3796        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3797        res[i]=std::accumulate(tmp,tmp+3,0.);
3798      }
3799 }
3800
3801 /*!
3802  * 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. 
3803  * \a this is expected to be a mesh so that its space dimension is equal to its
3804  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3805  * 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).
3806  
3807  * 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
3808  * 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).
3809  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3810  *
3811  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3812  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3813  *
3814  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3815  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3816  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3817  * \return the positive value of the distance.
3818  * \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
3819  * dimension - 1.
3820  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3821  */
3822 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3823 {
3824   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3825   if(meshDim!=spaceDim-1)
3826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3827   if(meshDim!=2 && meshDim!=1)
3828     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3829   checkFullyDefined();
3830   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3831     { 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()); }
3832   DataArrayInt *ret1=0;
3833   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3834   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3835   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3836   cellId=*ret1Safe->begin();
3837   return *ret0->begin();
3838 }
3839
3840 /*!
3841  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3842  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3843  * 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
3844  * 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).
3845  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3846  * 
3847  * \a this is expected to be a mesh so that its space dimension is equal to its
3848  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3849  * 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).
3850  *
3851  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3852  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3853  *
3854  * \param [in] pts the list of points in which each tuple represents a point
3855  * \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.
3856  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3857  * \throw if number of components of \a pts is not equal to the space dimension.
3858  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3859  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3860  */
3861 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3862 {
3863   if(!pts)
3864     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3865   pts->checkAllocated();
3866   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3867   if(meshDim!=spaceDim-1)
3868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3869   if(meshDim!=2 && meshDim!=1)
3870     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3871   if(pts->getNumberOfComponents()!=spaceDim)
3872     {
3873       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3874       throw INTERP_KERNEL::Exception(oss.str().c_str());
3875     }
3876   checkFullyDefined();
3877   int nbCells=getNumberOfCells();
3878   if(nbCells==0)
3879     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3880   int nbOfPts=pts->getNumberOfTuples();
3881   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3883   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3884   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3885   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3886   const double *bbox(bboxArr->begin());
3887   switch(spaceDim)
3888     {
3889     case 3:
3890       {
3891         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3892         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3893           {
3894             double x=std::numeric_limits<double>::max();
3895             std::vector<int> elems;
3896             myTree.getMinDistanceOfMax(ptsPtr,x);
3897             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3898             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3899           }
3900         break;
3901       }
3902     case 2:
3903       {
3904         BBTreeDst<2> myTree(bbox,0,0,nbCells);
3905         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3906           {
3907             double x=std::numeric_limits<double>::max();
3908             std::vector<int> elems;
3909             myTree.getMinDistanceOfMax(ptsPtr,x);
3910             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3911             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3912           }
3913         break;
3914       }
3915     default:
3916       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3917     }
3918   cellIds=ret1.retn();
3919   return ret0.retn();
3920 }
3921
3922 /*!
3923  * \param [in] pt the start pointer (included) of the coordinates of the point
3924  * \param [in] cellIdsBg the start pointer (included) of cellIds
3925  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3926  * \param [in] nc nodal connectivity
3927  * \param [in] ncI nodal connectivity index
3928  * \param [in,out] ret0 the min distance between \a this and the external input point
3929  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3930  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3931  */
3932 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)
3933 {
3934   cellId=-1;
3935   ret0=std::numeric_limits<double>::max();
3936   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3937     {
3938       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3939         {
3940         case INTERP_KERNEL::NORM_TRI3:
3941           {
3942             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3943             if(tmp<ret0)
3944               { ret0=tmp; cellId=*zeCell; }
3945             break;
3946           }
3947         case INTERP_KERNEL::NORM_QUAD4:
3948         case INTERP_KERNEL::NORM_POLYGON:
3949           {
3950             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3951             if(tmp<ret0)
3952               { ret0=tmp; cellId=*zeCell; }
3953             break;
3954           }
3955         default:
3956           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3957         }
3958     }
3959 }
3960
3961 /*!
3962  * \param [in] pt the start pointer (included) of the coordinates of the point
3963  * \param [in] cellIdsBg the start pointer (included) of cellIds
3964  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3965  * \param [in] nc nodal connectivity
3966  * \param [in] ncI nodal connectivity index
3967  * \param [in,out] ret0 the min distance between \a this and the external input point
3968  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3969  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3970  */
3971 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)
3972 {
3973   cellId=-1;
3974   ret0=std::numeric_limits<double>::max();
3975   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3976     {
3977        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3978         {
3979         case INTERP_KERNEL::NORM_SEG2:
3980           {
3981             std::size_t uselessEntry=0;
3982             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3983             tmp=sqrt(tmp);
3984             if(tmp<ret0)
3985               { ret0=tmp; cellId=*zeCell; }
3986             break;
3987           }
3988         default:
3989           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3990         }
3991     }
3992 }
3993
3994 /*!
3995  * Finds cells in contact with a ball (i.e. a point with precision). 
3996  * \warning This method is suitable if the caller intends to evaluate only one
3997  *          point, for more points getCellsContainingPoints() is recommended as it is
3998  *          faster. 
3999  *  \param [in] pos - array of coordinates of the ball central point.
4000  *  \param [in] eps - ball radius.
4001  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4002  *         if there are no such cells.
4003  *  \throw If the coordinates array is not set.
4004  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4005  */
4006 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4007 {
4008   std::vector<int> elts;
4009   getCellsContainingPoint(pos,eps,elts);
4010   if(elts.empty())
4011     return -1;
4012   return elts.front();
4013 }
4014
4015 /*!
4016  * Finds cells in contact with a ball (i.e. a point with precision).
4017  * \warning This method is suitable if the caller intends to evaluate only one
4018  *          point, for more points getCellsContainingPoints() is recommended as it is
4019  *          faster. 
4020  *  \param [in] pos - array of coordinates of the ball central point.
4021  *  \param [in] eps - ball radius.
4022  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4023  *         before inserting ids.
4024  *  \throw If the coordinates array is not set.
4025  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4026  *
4027  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4028  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4029  */
4030 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4031 {
4032   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4033   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4034   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4035 }
4036
4037 /// @cond INTERNAL
4038
4039 namespace ParaMEDMEM
4040 {
4041   template<const int SPACEDIMM>
4042   class DummyClsMCUG
4043   {
4044   public:
4045     static const int MY_SPACEDIM=SPACEDIMM;
4046     static const int MY_MESHDIM=8;
4047     typedef int MyConnType;
4048     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4049     // begin
4050     // useless, but for windows compilation ...
4051     const double* getCoordinatesPtr() const { return 0; }
4052     const int* getConnectivityPtr() const { return 0; }
4053     const int* getConnectivityIndexPtr() const { return 0; }
4054     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4055     // end
4056   };
4057
4058   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4059   {
4060     INTERP_KERNEL::Edge *ret=0;
4061     switch(typ)
4062       {
4063       case INTERP_KERNEL::NORM_SEG2:
4064         {
4065           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4066           break;
4067         }
4068       case INTERP_KERNEL::NORM_SEG3:
4069         {
4070           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4071           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4072           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4073           bool colinearity=inters.areColinears();
4074           delete e1; delete e2;
4075           if(colinearity)
4076             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4077           else
4078             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4079           mapp2[bg[2]].second=false;
4080           break;
4081         }
4082       default:
4083         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4084       }
4085     return ret;
4086   }
4087
4088   /*!
4089    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
4090    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4091    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4092    */
4093   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4094   {
4095     mapp.clear();
4096     std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;//bool is for a flag specifying if node is boundary (true) or only a middle for SEG3.
4097     const double *coo=mDesc->getCoords()->getConstPointer();
4098     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4099     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4100     std::set<int> s;
4101     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4102       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4103     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4104       {
4105         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4106         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4107       }
4108     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4109     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4110       {
4111         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4112         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4113       }
4114     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4115       {
4116         if((*it2).second.second)
4117           mapp[(*it2).second.first]=(*it2).first;
4118         ((*it2).second.first)->decrRef();
4119       }
4120     return ret;
4121   }
4122
4123   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4124   {
4125     if(nodeId>=offset2)
4126       {
4127         int locId=nodeId-offset2;
4128         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4129       }
4130     if(nodeId>=offset1)
4131       {
4132         int locId=nodeId-offset1;
4133         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4134       }
4135     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4136   }
4137
4138   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4139                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4140                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4141   {
4142     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4143       {
4144         int eltId1=abs(*desc1)-1;
4145         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4146           {
4147             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4148             if(it==mappRev.end())
4149               {
4150                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4151                 mapp[node]=*it1;
4152                 mappRev[*it1]=node;
4153               }
4154           }
4155       }
4156   }
4157 }
4158
4159 /// @endcond
4160
4161 template<int SPACEDIM>
4162 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4163                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4164 {
4165   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4166   int *eltsIndexPtr(eltsIndex->getPointer());
4167   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4168   const double *bbox(bboxArr->begin());
4169   int nbOfCells=getNumberOfCells();
4170   const int *conn=_nodal_connec->getConstPointer();
4171   const int *connI=_nodal_connec_index->getConstPointer();
4172   double bb[2*SPACEDIM];
4173   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4174   for(int i=0;i<nbOfPoints;i++)
4175     {
4176       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4177       for(int j=0;j<SPACEDIM;j++)
4178         {
4179           bb[2*j]=pos[SPACEDIM*i+j];
4180           bb[2*j+1]=pos[SPACEDIM*i+j];
4181         }
4182       std::vector<int> candidates;
4183       myTree.getIntersectingElems(bb,candidates);
4184       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4185         {
4186           int sz=connI[(*iter)+1]-connI[*iter]-1;
4187           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4188                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4189                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4190             {
4191               eltsIndexPtr[i+1]++;
4192               elts->pushBackSilent(*iter);
4193             }
4194         }
4195     }
4196 }
4197 /*!
4198  * Finds cells in contact with several balls (i.e. points with precision).
4199  * This method is an extension of getCellContainingPoint() and
4200  * getCellsContainingPoint() for the case of multiple points.
4201  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4202  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4203  *         this->getSpaceDimension() * \a nbOfPoints 
4204  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4205  *  \param [in] eps - radius of balls (i.e. the precision).
4206  *  \param [out] elts - vector returning ids of found cells.
4207  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4208  *         dividing cell ids in \a elts into groups each referring to one
4209  *         point. Its every element (except the last one) is an index pointing to the
4210  *         first id of a group of cells. For example cells in contact with the *i*-th
4211  *         point are described by following range of indices:
4212  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4213  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4214  *         Number of cells in contact with the *i*-th point is
4215  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4216  *  \throw If the coordinates array is not set.
4217  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4218  *
4219  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4220  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4221  */
4222 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4223                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4224 {
4225   int spaceDim=getSpaceDimension();
4226   int mDim=getMeshDimension();
4227   if(spaceDim==3)
4228     {
4229       if(mDim==3)
4230         {
4231           const double *coords=_coords->getConstPointer();
4232           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4233         }
4234       /*else if(mDim==2)
4235         {
4236           
4237         }*/
4238       else
4239         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4240     }
4241   else if(spaceDim==2)
4242     {
4243       if(mDim==2)
4244         {
4245           const double *coords=_coords->getConstPointer();
4246           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4247         }
4248       else
4249         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4250     }
4251   else if(spaceDim==1)
4252     {
4253       if(mDim==1)
4254         {
4255           const double *coords=_coords->getConstPointer();
4256           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4257         }
4258       else
4259         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4260     }
4261   else
4262     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4263 }
4264
4265 /*!
4266  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4267  * least two its edges intersect each other anywhere except their extremities. An
4268  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4269  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4270  *         cleared before filling in.
4271  *  \param [in] eps - precision.
4272  *  \throw If \a this->getMeshDimension() != 2.
4273  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4274  */
4275 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4276 {
4277   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4278   if(getMeshDimension()!=2)
4279     throw INTERP_KERNEL::Exception(msg);
4280   int spaceDim=getSpaceDimension();
4281   if(spaceDim!=2 && spaceDim!=3)
4282     throw INTERP_KERNEL::Exception(msg);
4283   const int *conn=_nodal_connec->getConstPointer();
4284   const int *connI=_nodal_connec_index->getConstPointer();
4285   int nbOfCells=getNumberOfCells();
4286   std::vector<double> cell2DinS2;
4287   for(int i=0;i<nbOfCells;i++)
4288     {
4289       int offset=connI[i];
4290       int nbOfNodesForCell=connI[i+1]-offset-1;
4291       if(nbOfNodesForCell<=3)
4292         continue;
4293       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4294       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4295       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4296         cells.push_back(i);
4297       cell2DinS2.clear();
4298     }
4299 }
4300
4301 /*!
4302  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4303  *
4304  * 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.
4305  * 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.
4306  * 
4307  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4308  * This convex envelop is computed using Jarvis march algorithm.
4309  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4310  * 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)
4311  * 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.
4312  *
4313  * \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.
4314  */
4315 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4316 {
4317   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4318     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4319   checkFullyDefined();
4320   const double *coords=getCoords()->getConstPointer();
4321   int nbOfCells=getNumberOfCells();
4322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4323   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4324   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4325   int *workIndexOut=nodalConnecIndexOut->getPointer();
4326   *workIndexOut=0;
4327   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4328   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4329   std::set<INTERP_KERNEL::NormalizedCellType> types;
4330   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4331   isChanged->alloc(0,1);
4332   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4333     {
4334       int pos=nodalConnecOut->getNumberOfTuples();
4335       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4336         isChanged->pushBackSilent(i);
4337       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4338       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4339     }
4340   if(isChanged->empty())
4341     return 0;
4342   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4343   _types=types;
4344   return isChanged.retn();
4345 }
4346
4347 /*!
4348  * This method is \b NOT const because it can modify \a this.
4349  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4350  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4351  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4352  * \b 1 for translation and rotation around point of 'mesh1D'.
4353  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4354  */
4355 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4356 {
4357   checkFullyDefined();
4358   mesh1D->checkFullyDefined();
4359   if(!mesh1D->isContiguous1D())
4360     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4361   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4362     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4363   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4364     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4365   if(mesh1D->getMeshDimension()!=1)
4366     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4367   bool isQuad=false;
4368   if(isPresenceOfQuadratic())
4369     {
4370       if(mesh1D->isFullyQuadratic())
4371         isQuad=true;
4372       else
4373         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4374     }
4375   zipCoords();
4376   int oldNbOfNodes=getNumberOfNodes();
4377   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4378   switch(policy)
4379     {
4380     case 0:
4381       {
4382         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4383         break;
4384       }
4385     case 1:
4386       {
4387         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4388         break;
4389       }
4390     default:
4391       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4392     }
4393   setCoords(newCoords);
4394   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4395   updateTime();
4396   return ret.retn();
4397 }
4398
4399 /*!
4400  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4401  * If it is not the case an exception will be thrown.
4402  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4403  * intersection of plane defined by ('origin','vec').
4404  * This method has one in/out parameter : 'cut3DCurve'.
4405  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4406  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4407  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4408  * This method will throw an exception if \a this contains a non linear segment.
4409  */
4410 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4411 {
4412   checkFullyDefined();
4413   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4415   int ncells=getNumberOfCells();
4416   int nnodes=getNumberOfNodes();
4417   double vec2[3],vec3[3],vec4[3];
4418   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4419   if(normm<1e-6)
4420     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4421   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4422   const int *conn=_nodal_connec->getConstPointer();
4423   const int *connI=_nodal_connec_index->getConstPointer();
4424   const double *coo=_coords->getConstPointer();
4425   std::vector<double> addCoo;
4426   for(int i=0;i<ncells;i++)
4427     {
4428       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4429         {
4430           if(cut3DCurve[i]==-2)
4431             {
4432               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4433               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];
4434               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4435               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4436               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4437                 {
4438                   const double *st2=coo+3*st;
4439                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4440                   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]));
4441                   if(pos>eps && pos<1-eps)
4442                     {
4443                       int nNode=((int)addCoo.size())/3;
4444                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4445                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4446                       cut3DCurve[i]=nnodes+nNode;
4447                     }
4448                 }
4449             }
4450         }
4451       else
4452         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4453     }
4454   if(!addCoo.empty())
4455     {
4456       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4457       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4458       coo2->alloc(newNbOfNodes,3);
4459       double *tmp=coo2->getPointer();
4460       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4461       std::copy(addCoo.begin(),addCoo.end(),tmp);
4462       DataArrayDouble::SetArrayIn(coo2,_coords);
4463     }
4464 }
4465
4466 /*!
4467  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4468  * \param mesh1D is the input 1D mesh used for translation computation.
4469  * \return newCoords new coords filled by this method. 
4470  */
4471 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4472 {
4473   int oldNbOfNodes=getNumberOfNodes();
4474   int nbOf1DCells=mesh1D->getNumberOfCells();
4475   int spaceDim=getSpaceDimension();
4476   DataArrayDouble *ret=DataArrayDouble::New();
4477   std::vector<bool> isQuads;
4478   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4479   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4480   double *retPtr=ret->getPointer();
4481   const double *coords=getCoords()->getConstPointer();
4482   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4483   std::vector<int> v;
4484   std::vector<double> c;
4485   double vec[3];
4486   v.reserve(3);
4487   c.reserve(6);
4488   for(int i=0;i<nbOf1DCells;i++)
4489     {
4490       v.resize(0);
4491       mesh1D->getNodeIdsOfCell(i,v);
4492       c.resize(0);
4493       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4494       mesh1D->getCoordinatesOfNode(v[0],c);
4495       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4496       for(int j=0;j<oldNbOfNodes;j++)
4497         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4498       if(isQuad)
4499         {
4500           c.resize(0);
4501           mesh1D->getCoordinatesOfNode(v[1],c);
4502           mesh1D->getCoordinatesOfNode(v[0],c);
4503           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4504           for(int j=0;j<oldNbOfNodes;j++)
4505             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4506         }
4507     }
4508   ret->copyStringInfoFrom(*getCoords());
4509   return ret;
4510 }
4511
4512 /*!
4513  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4514  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4515  * \return newCoords new coords filled by this method. 
4516  */
4517 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4518 {
4519   if(mesh1D->getSpaceDimension()==2)
4520     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4521   if(mesh1D->getSpaceDimension()==3)
4522     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4523   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4524 }
4525
4526 /*!
4527  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4528  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4529  * \return newCoords new coords filled by this method. 
4530  */
4531 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4532 {
4533   if(isQuad)
4534     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4535   int oldNbOfNodes=getNumberOfNodes();
4536   int nbOf1DCells=mesh1D->getNumberOfCells();
4537   if(nbOf1DCells<2)
4538     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4539   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4540   int nbOfLevsInVec=nbOf1DCells+1;
4541   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4542   double *retPtr=ret->getPointer();
4543   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4544   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4545   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4546   tmp->setCoords(tmp2);
4547   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4548   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4549   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4550   for(int i=1;i<nbOfLevsInVec;i++)
4551     {
4552       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4553       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4554       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4555       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4556       tmp->translate(vec);
4557       double tmp3[2],radius,alpha,alpha0;
4558       const double *p0=i+1<nbOfLevsInVec?begin:third;
4559       const double *p1=i+1<nbOfLevsInVec?end:begin;
4560       const double *p2=i+1<nbOfLevsInVec?third:end;
4561       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4562       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]);
4563       double angle=acos(cosangle/(radius*radius));
4564       tmp->rotate(end,0,angle);
4565       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4566     }
4567   return ret.retn();
4568 }
4569
4570 /*!
4571  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4572  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4573  * \return newCoords new coords filled by this method. 
4574  */
4575 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4576 {
4577   if(isQuad)
4578     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4579   int oldNbOfNodes=getNumberOfNodes();
4580   int nbOf1DCells=mesh1D->getNumberOfCells();
4581   if(nbOf1DCells<2)
4582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4583   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4584   int nbOfLevsInVec=nbOf1DCells+1;
4585   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4586   double *retPtr=ret->getPointer();
4587   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4588   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4589   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4590   tmp->setCoords(tmp2);
4591   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4592   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4593   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4594   for(int i=1;i<nbOfLevsInVec;i++)
4595     {
4596       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4597       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4598       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4599       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4600       tmp->translate(vec);
4601       double tmp3[2],radius,alpha,alpha0;
4602       const double *p0=i+1<nbOfLevsInVec?begin:third;
4603       const double *p1=i+1<nbOfLevsInVec?end:begin;
4604       const double *p2=i+1<nbOfLevsInVec?third:end;
4605       double vecPlane[3]={
4606         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4607         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4608         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4609       };
4610       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4611       if(norm>1.e-7)
4612         {
4613           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4614           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4615           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4616           double s2=norm2;
4617           double c2=cos(asin(s2));
4618           double m[3][3]={
4619             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4620             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4621             {-vec2[1]*s2, vec2[0]*s2, c2}
4622           };
4623           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]};
4624           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]};
4625           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]};
4626           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4627           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]);
4628           double angle=acos(cosangle/(radius*radius));
4629           tmp->rotate(end,vecPlane,angle);
4630           
4631         }
4632       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4633     }
4634   return ret.retn();
4635 }
4636
4637 /*!
4638  * This method is private because not easy to use for end user. This method is const contrary to
4639  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4640  * the coords sorted slice by slice.
4641  * \param isQuad specifies presence of quadratic cells.
4642  */
4643 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4644 {
4645   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4646   int nbOf2DCells=getNumberOfCells();
4647   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4648   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4649   const int *conn=_nodal_connec->getConstPointer();
4650   const int *connI=_nodal_connec_index->getConstPointer();
4651   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4652   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4653   newConnI->alloc(nbOf3DCells+1,1);
4654   int *newConnIPtr=newConnI->getPointer();
4655   *newConnIPtr++=0;
4656   std::vector<int> newc;
4657   for(int j=0;j<nbOf2DCells;j++)
4658     {
4659       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4660       *newConnIPtr++=(int)newc.size();
4661     }
4662   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4663   int *newConnPtr=newConn->getPointer();
4664   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4665   newConnIPtr=newConnI->getPointer();
4666   for(int iz=0;iz<nbOf1DCells;iz++)
4667     {
4668       if(iz!=0)
4669         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4670       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4671         {
4672           int icell=(int)(iter-newc.begin());
4673           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4674             {
4675               if(*iter!=-1)
4676                 *newConnPtr=(*iter)+iz*deltaPerLev;
4677               else
4678                 *newConnPtr=-1;
4679             }
4680           else
4681             *newConnPtr=(*iter);
4682         }
4683     }
4684   ret->setConnectivity(newConn,newConnI,true);
4685   ret->setCoords(getCoords());
4686   return ret;
4687 }
4688
4689 /*!
4690  * Checks if \a this mesh is constituted by only quadratic cells.
4691  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4692  *  \throw If the coordinates array is not set.
4693  *  \throw If the nodal connectivity of cells is not defined.
4694  */
4695 bool MEDCouplingUMesh::isFullyQuadratic() const
4696 {
4697   checkFullyDefined();
4698   bool ret=true;
4699   int nbOfCells=getNumberOfCells();
4700   for(int i=0;i<nbOfCells && ret;i++)
4701     {
4702       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4703       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4704       ret=cm.isQuadratic();
4705     }
4706   return ret;
4707 }
4708
4709 /*!
4710  * Checks if \a this mesh includes any quadratic cell.
4711  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4712  *  \throw If the coordinates array is not set.
4713  *  \throw If the nodal connectivity of cells is not defined.
4714  */
4715 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4716 {
4717   checkFullyDefined();
4718   bool ret=false;
4719   int nbOfCells=getNumberOfCells();
4720   for(int i=0;i<nbOfCells && !ret;i++)
4721     {
4722       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4723       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4724       ret=cm.isQuadratic();
4725     }
4726   return ret;
4727 }
4728
4729 /*!
4730  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4731  * this mesh, it remains unchanged.
4732  *  \throw If the coordinates array is not set.
4733  *  \throw If the nodal connectivity of cells is not defined.
4734  */
4735 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4736 {
4737   checkFullyDefined();
4738   int nbOfCells=getNumberOfCells();
4739   int delta=0;
4740   const int *iciptr=_nodal_connec_index->getConstPointer();
4741   for(int i=0;i<nbOfCells;i++)
4742     {
4743       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4744       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4745       if(cm.isQuadratic())
4746         {
4747           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4748           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4749           if(!cml.isDynamic())
4750             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4751           else
4752             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4753         }
4754     }
4755   if(delta==0)
4756     return ;
4757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4759   const int *icptr=_nodal_connec->getConstPointer();
4760   newConn->alloc(getMeshLength()-delta,1);
4761   newConnI->alloc(nbOfCells+1,1);
4762   int *ocptr=newConn->getPointer();
4763   int *ociptr=newConnI->getPointer();
4764   *ociptr=0;
4765   _types.clear();
4766   for(int i=0;i<nbOfCells;i++,ociptr++)
4767     {
4768       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4769       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4770       if(!cm.isQuadratic())
4771         {
4772           _types.insert(type);
4773           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4774           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4775         }
4776       else
4777         {
4778           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4779           _types.insert(typel);
4780           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4781           int newNbOfNodes=cml.getNumberOfNodes();
4782           if(cml.isDynamic())
4783             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4784           *ocptr++=(int)typel;
4785           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4786           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4787         }
4788     }
4789   setConnectivity(newConn,newConnI,false);
4790 }
4791
4792 /*!
4793  * This method converts all linear cell in \a this to quadratic one.
4794  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4795  * 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)
4796  * 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.
4797  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4798  * end of the existing coordinates.
4799  * 
4800  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4801  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4802  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4803  * 
4804  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4805  *
4806  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4807  */
4808 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4809 {
4810   DataArrayInt *conn=0,*connI=0;
4811   DataArrayDouble *coords=0;
4812   std::set<INTERP_KERNEL::NormalizedCellType> types;
4813   checkFullyDefined();
4814   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4815   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4816   int meshDim=getMeshDimension();
4817   switch(conversionType)
4818     {
4819     case 0:
4820       switch(meshDim)
4821         {
4822         case 1:
4823           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4824           connSafe=conn; connISafe=connI; coordsSafe=coords;
4825           break;
4826         case 2:
4827           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4828           connSafe=conn; connISafe=connI; coordsSafe=coords;
4829           break;
4830         case 3:
4831           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4832           connSafe=conn; connISafe=connI; coordsSafe=coords;
4833           break;
4834         default:
4835           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4836         }
4837       break;
4838     case 1:
4839       {
4840         switch(meshDim)
4841         {
4842         case 1:
4843           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4844           connSafe=conn; connISafe=connI; coordsSafe=coords;
4845           break;
4846         case 2:
4847           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4848           connSafe=conn; connISafe=connI; coordsSafe=coords;
4849           break;
4850         case 3:
4851           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4852           connSafe=conn; connISafe=connI; coordsSafe=coords;
4853           break;
4854         default:
4855           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4856         }
4857         break;
4858       }
4859     default:
4860       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4861     }
4862   setConnectivity(connSafe,connISafe,false);
4863   _types=types;
4864   setCoords(coordsSafe);
4865   return ret.retn();
4866 }
4867
4868 /*!
4869  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4870  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4871  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4872  */
4873 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4874 {
4875   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4879   int nbOfCells=getNumberOfCells();
4880   int nbOfNodes=getNumberOfNodes();
4881   const int *cPtr=_nodal_connec->getConstPointer();
4882   const int *icPtr=_nodal_connec_index->getConstPointer();
4883   int lastVal=0,offset=nbOfNodes;
4884   for(int i=0;i<nbOfCells;i++,icPtr++)
4885     {
4886       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4887       if(type==INTERP_KERNEL::NORM_SEG2)
4888         {
4889           types.insert(INTERP_KERNEL::NORM_SEG3);
4890           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4891           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4892           newConn->pushBackSilent(offset++);
4893           lastVal+=4;
4894           newConnI->pushBackSilent(lastVal);
4895           ret->pushBackSilent(i);
4896         }
4897       else
4898         {
4899           types.insert(type);
4900           lastVal+=(icPtr[1]-icPtr[0]);
4901           newConnI->pushBackSilent(lastVal);
4902           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4903         }
4904     }
4905   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4906   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4907   return ret.retn();
4908 }
4909
4910 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)
4911 {
4912   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4913   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4915   //
4916   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4917   DataArrayInt *conn1D=0,*conn1DI=0;
4918   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4919   DataArrayDouble *coordsTmp=0;
4920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4921   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4923   const int *c1DPtr=conn1D->begin();
4924   const int *c1DIPtr=conn1DI->begin();
4925   int nbOfCells=getNumberOfCells();
4926   const int *cPtr=_nodal_connec->getConstPointer();
4927   const int *icPtr=_nodal_connec_index->getConstPointer();
4928   int lastVal=0;
4929   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4930     {
4931       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4932       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4933       if(!cm.isQuadratic())
4934         {
4935           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4936           types.insert(typ2); newConn->pushBackSilent(typ2);
4937           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4938           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4939             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4940           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4941           newConnI->pushBackSilent(lastVal);
4942           ret->pushBackSilent(i);
4943         }
4944       else
4945         {
4946           types.insert(typ);
4947           lastVal+=(icPtr[1]-icPtr[0]);
4948           newConnI->pushBackSilent(lastVal);
4949           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4950         }
4951     }
4952   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4953   return ret.retn();
4954 }
4955
4956 /*!
4957  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4958  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4959  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4960  */
4961 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4962 {
4963   
4964   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4965   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4966   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4967 }
4968
4969 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4970 {
4971   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4972   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4973   //
4974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4976   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4977   //
4978   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4979   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4980   DataArrayInt *conn1D=0,*conn1DI=0;
4981   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4982   DataArrayDouble *coordsTmp=0;
4983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4984   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4985   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4986   const int *c1DPtr=conn1D->begin();
4987   const int *c1DIPtr=conn1DI->begin();
4988   int nbOfCells=getNumberOfCells();
4989   const int *cPtr=_nodal_connec->getConstPointer();
4990   const int *icPtr=_nodal_connec_index->getConstPointer();
4991   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4992   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4993     {
4994       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4995       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4996       if(!cm.isQuadratic())
4997         {
4998           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4999           types.insert(typ2); newConn->pushBackSilent(typ2);
5000           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5001           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5002             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5003           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5004           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5005           newConnI->pushBackSilent(lastVal);
5006           ret->pushBackSilent(i);
5007         }
5008       else
5009         {
5010           types.insert(typ);
5011           lastVal+=(icPtr[1]-icPtr[0]);
5012           newConnI->pushBackSilent(lastVal);
5013           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5014         }
5015     }
5016   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5017   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5018   return ret.retn();
5019 }
5020
5021 /*!
5022  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5023  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5024  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5025  */
5026 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5027 {
5028   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5029   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5030   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5031 }
5032
5033 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5034 {
5035   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5036   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5037   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5038   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5039   //
5040   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5041   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5042   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5043   //
5044   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5045   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5046   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5047   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5048   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5049   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5051   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5052   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5053   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5054   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5055   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5056   int nbOfCells=getNumberOfCells();
5057   const int *cPtr=_nodal_connec->getConstPointer();
5058   const int *icPtr=_nodal_connec_index->getConstPointer();
5059   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5060   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5061     {
5062       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5063       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5064       if(!cm.isQuadratic())
5065         {
5066           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5067           if(typ2==INTERP_KERNEL::NORM_ERROR)
5068             {
5069               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5070               throw INTERP_KERNEL::Exception(oss.str().c_str());
5071             }
5072           types.insert(typ2); newConn->pushBackSilent(typ2);
5073           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5074           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5075             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5076           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5077             {
5078               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5079               int tmpPos=newConn->getNumberOfTuples();
5080               newConn->pushBackSilent(nodeId2);
5081               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5082             }
5083           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5084           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5085           newConnI->pushBackSilent(lastVal);
5086           ret->pushBackSilent(i);
5087         }
5088       else
5089         {
5090           types.insert(typ);
5091           lastVal+=(icPtr[1]-icPtr[0]);
5092           newConnI->pushBackSilent(lastVal);
5093           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5094         }
5095     }
5096   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5097   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5098   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5099   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5100   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5101   int *c=newConn->getPointer();
5102   const int *cI(newConnI->begin());
5103   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5104     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5105   offset=coordsTmp2Safe->getNumberOfTuples();
5106   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5107     c[cI[(*elt)+1]-1]+=offset;
5108   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5109   return ret.retn();
5110 }
5111
5112 /*!
5113  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5114  * so that the number of cells remains the same. Quadratic faces are converted to
5115  * polygons. This method works only for 2D meshes in
5116  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5117  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5118  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5119  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5120  *         a polylinized edge constituting the input polygon.
5121  *  \throw If the coordinates array is not set.
5122  *  \throw If the nodal connectivity of cells is not defined.
5123  *  \throw If \a this->getMeshDimension() != 2.
5124  *  \throw If \a this->getSpaceDimension() != 2.
5125  */
5126 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5127 {
5128   checkFullyDefined();
5129   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5130     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5131   double epsa=fabs(eps);
5132   if(epsa<std::numeric_limits<double>::min())
5133     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 !");
5134   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5136   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5137   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5138   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5139   revDesc1=0; revDescIndx1=0;
5140   mDesc->tessellate2DCurve(eps);
5141   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5142   setCoords(mDesc->getCoords());
5143 }
5144
5145 /*!
5146  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5147  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5148  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5149  *         a sub-divided edge.
5150  *  \throw If the coordinates array is not set.
5151  *  \throw If the nodal connectivity of cells is not defined.
5152  *  \throw If \a this->getMeshDimension() != 1.
5153  *  \throw If \a this->getSpaceDimension() != 2.
5154  */
5155 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5156 {
5157   checkFullyDefined();
5158   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5159     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5160   double epsa=fabs(eps);
5161   if(epsa<std::numeric_limits<double>::min())
5162     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 !");
5163   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5164   int nbCells=getNumberOfCells();
5165   int nbNodes=getNumberOfNodes();
5166   const int *conn=_nodal_connec->getConstPointer();
5167   const int *connI=_nodal_connec_index->getConstPointer();
5168   const double *coords=_coords->getConstPointer();
5169   std::vector<double> addCoo;
5170   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5171   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5172   newConnI->alloc(nbCells+1,1);
5173   int *newConnIPtr=newConnI->getPointer();
5174   *newConnIPtr=0;
5175   int tmp1[3];
5176   INTERP_KERNEL::Node *tmp2[3];
5177   std::set<INTERP_KERNEL::NormalizedCellType> types;
5178   for(int i=0;i<nbCells;i++,newConnIPtr++)
5179     {
5180       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5181       if(cm.isQuadratic())
5182         {//assert(connI[i+1]-connI[i]-1==3)
5183           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5184           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5185           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5186           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5187           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5188           if(eac)
5189             {
5190               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5191               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5192               delete eac;
5193               newConnIPtr[1]=(int)newConn.size();
5194             }
5195           else
5196             {
5197               types.insert(INTERP_KERNEL::NORM_SEG2);
5198               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5199               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5200               newConnIPtr[1]=newConnIPtr[0]+3;
5201             }
5202         }
5203       else
5204         {
5205           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5206           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5207           newConnIPtr[1]=newConnIPtr[0]+3;
5208         }
5209     }
5210   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5211     return ;
5212   _types=types;
5213   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5214   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5215   newConnArr->alloc((int)newConn.size(),1);
5216   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5217   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5218   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5219   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5220   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5221   std::copy(addCoo.begin(),addCoo.end(),work);
5222   DataArrayDouble::SetArrayIn(newCoords,_coords);
5223   updateTime();
5224 }
5225
5226 /*!
5227  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5228  * In addition, returns an array mapping new cells to old ones. <br>
5229  * This method typically increases the number of cells in \a this mesh
5230  * but the number of nodes remains \b unchanged.
5231  * That's why the 3D splitting policies
5232  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5233  *  \param [in] policy - specifies a pattern used for splitting.
5234  * The semantic of \a policy is:
5235  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5236  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5237  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5238  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5239  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5240  *          an id of old cell producing it. The caller is to delete this array using
5241  *         decrRef() as it is no more needed. 
5242  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5243  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5244  *          and \a this->getMeshDimension() != 3. 
5245  *  \throw If \a policy is not one of the four discussed above.
5246  *  \throw If the nodal connectivity of cells is not defined.
5247  * \sa MEDCouplingUMesh::tetrahedrize
5248  */
5249 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5250 {
5251   switch(policy)
5252     {
5253     case 0:
5254       return simplexizePol0();
5255     case 1:
5256       return simplexizePol1();
5257     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5258       return simplexizePlanarFace5();
5259     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5260       return simplexizePlanarFace6();
5261     default:
5262       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be :\n  - 0 or 1 (only available for meshdim=2) \n  - PLANAR_FACE_5, PLANAR_FACE_6  (only for meshdim=3)");
5263     }
5264 }
5265
5266 /*!
5267  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5268  * - 1D: INTERP_KERNEL::NORM_SEG2
5269  * - 2D: INTERP_KERNEL::NORM_TRI3
5270  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5271  *
5272  * This method is useful for users that need to use P1 field services as
5273  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5274  * All these methods need mesh support containing only simplex cells.
5275  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5276  *  \throw If the coordinates array is not set.
5277  *  \throw If the nodal connectivity of cells is not defined.
5278  *  \throw If \a this->getMeshDimension() < 1.
5279  */
5280 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5281 {
5282   checkFullyDefined();
5283   int mdim=getMeshDimension();
5284   if(mdim<1 || mdim>3)
5285     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5286   int nbCells=getNumberOfCells();
5287   const int *conn=_nodal_connec->getConstPointer();
5288   const int *connI=_nodal_connec_index->getConstPointer();
5289   for(int i=0;i<nbCells;i++)
5290     {
5291       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5292       if(!cm.isSimplex())
5293         return false;
5294     }
5295   return true;
5296 }
5297
5298 /*!
5299  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5300  */
5301 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5302 {
5303   checkConnectivityFullyDefined();
5304   if(getMeshDimension()!=2)
5305     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5306   int nbOfCells=getNumberOfCells();
5307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5308   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5309   ret->alloc(nbOfCells+nbOfCutCells,1);
5310   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5311   int *retPt=ret->getPointer();
5312   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5313   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5314   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5315   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5316   int *pt=newConn->getPointer();
5317   int *ptI=newConnI->getPointer();
5318   ptI[0]=0;
5319   const int *oldc=_nodal_connec->getConstPointer();
5320   const int *ci=_nodal_connec_index->getConstPointer();
5321   for(int i=0;i<nbOfCells;i++,ci++)
5322     {
5323       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5324         {
5325           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5326                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5327           pt=std::copy(tmp,tmp+8,pt);
5328           ptI[1]=ptI[0]+4;
5329           ptI[2]=ptI[0]+8;
5330           *retPt++=i;
5331           *retPt++=i;
5332           ptI+=2;
5333         }
5334       else
5335         {
5336           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5337           ptI[1]=ptI[0]+ci[1]-ci[0];
5338           ptI++;
5339           *retPt++=i;
5340         }
5341     }
5342   _nodal_connec->decrRef();
5343   _nodal_connec=newConn.retn();
5344   _nodal_connec_index->decrRef();
5345   _nodal_connec_index=newConnI.retn();
5346   computeTypes();
5347   updateTime();
5348   return ret.retn();
5349 }
5350
5351 /*!
5352  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5353  */
5354 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5355 {
5356   checkConnectivityFullyDefined();
5357   if(getMeshDimension()!=2)
5358     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5359   int nbOfCells=getNumberOfCells();
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5361   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5362   ret->alloc(nbOfCells+nbOfCutCells,1);
5363   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5364   int *retPt=ret->getPointer();
5365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5367   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5368   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5369   int *pt=newConn->getPointer();
5370   int *ptI=newConnI->getPointer();
5371   ptI[0]=0;
5372   const int *oldc=_nodal_connec->getConstPointer();
5373   const int *ci=_nodal_connec_index->getConstPointer();
5374   for(int i=0;i<nbOfCells;i++,ci++)
5375     {
5376       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5377         {
5378           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5379                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5380           pt=std::copy(tmp,tmp+8,pt);
5381           ptI[1]=ptI[0]+4;
5382           ptI[2]=ptI[0]+8;
5383           *retPt++=i;
5384           *retPt++=i;
5385           ptI+=2;
5386         }
5387       else
5388         {
5389           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5390           ptI[1]=ptI[0]+ci[1]-ci[0];
5391           ptI++;
5392           *retPt++=i;
5393         }
5394     }
5395   _nodal_connec->decrRef();
5396   _nodal_connec=newConn.retn();
5397   _nodal_connec_index->decrRef();
5398   _nodal_connec_index=newConnI.retn();
5399   computeTypes();
5400   updateTime();
5401   return ret.retn();
5402 }
5403
5404 /*!
5405  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5406  */
5407 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5408 {
5409   checkConnectivityFullyDefined();
5410   if(getMeshDimension()!=3)
5411     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5412   int nbOfCells=getNumberOfCells();
5413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5414   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5415   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5416   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5417   int *retPt=ret->getPointer();
5418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5420   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5421   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5422   int *pt=newConn->getPointer();
5423   int *ptI=newConnI->getPointer();
5424   ptI[0]=0;
5425   const int *oldc=_nodal_connec->getConstPointer();
5426   const int *ci=_nodal_connec_index->getConstPointer();
5427   for(int i=0;i<nbOfCells;i++,ci++)
5428     {
5429       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5430         {
5431           for(int j=0;j<5;j++,pt+=5,ptI++)
5432             {
5433               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5434               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+3]+1];
5435               *retPt++=i;
5436               ptI[1]=ptI[0]+5;
5437             }
5438         }
5439       else
5440         {
5441           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5442           ptI[1]=ptI[0]+ci[1]-ci[0];
5443           ptI++;
5444           *retPt++=i;
5445         }
5446     }
5447   _nodal_connec->decrRef();
5448   _nodal_connec=newConn.retn();
5449   _nodal_connec_index->decrRef();
5450   _nodal_connec_index=newConnI.retn();
5451   computeTypes();
5452   updateTime();
5453   return ret.retn();
5454 }
5455
5456 /*!
5457  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5458  */
5459 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5460 {
5461   checkConnectivityFullyDefined();
5462   if(getMeshDimension()!=3)
5463     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5464   int nbOfCells=getNumberOfCells();
5465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5466   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5467   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5468   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5469   int *retPt=ret->getPointer();
5470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5472   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5473   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5474   int *pt=newConn->getPointer();
5475   int *ptI=newConnI->getPointer();
5476   ptI[0]=0;
5477   const int *oldc=_nodal_connec->getConstPointer();
5478   const int *ci=_nodal_connec_index->getConstPointer();
5479   for(int i=0;i<nbOfCells;i++,ci++)
5480     {
5481       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5482         {
5483           for(int j=0;j<6;j++,pt+=5,ptI++)
5484             {
5485               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5486               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+3]+1];
5487               *retPt++=i;
5488               ptI[1]=ptI[0]+5;
5489             }
5490         }
5491       else
5492         {
5493           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5494           ptI[1]=ptI[0]+ci[1]-ci[0];
5495           ptI++;
5496           *retPt++=i;
5497         }
5498     }
5499   _nodal_connec->decrRef();
5500   _nodal_connec=newConn.retn();
5501   _nodal_connec_index->decrRef();
5502   _nodal_connec_index=newConnI.retn();
5503   computeTypes();
5504   updateTime();
5505   return ret.retn();
5506 }
5507
5508 /*!
5509  * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5510  * This method completly ignore coordinates.
5511  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5512  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5513  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5514  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5515  */
5516 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5517 {
5518   checkFullyDefined();
5519   if(getMeshDimension()!=2)
5520     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5521   int nbOfCells=getNumberOfCells();
5522   int *connI=_nodal_connec_index->getPointer();
5523   int newConnLgth=0;
5524   for(int i=0;i<nbOfCells;i++,connI++)
5525     {
5526       int offset=descIndex[i];
5527       int nbOfEdges=descIndex[i+1]-offset;
5528       //
5529       bool ddirect=desc[offset+nbOfEdges-1]>0;
5530       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5531       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5532       for(int j=0;j<nbOfEdges;j++)
5533         {
5534           bool direct=desc[offset+j]>0;
5535           int edgeId=std::abs(desc[offset+j])-1;
5536           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5537             {
5538               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5539               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5540               int ref2=direct?id1:id2;
5541               if(ref==ref2)
5542                 {
5543                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5544                   newConnLgth+=nbOfSubNodes-1;
5545                   ref=direct?id2:id1;
5546                 }
5547               else
5548                 {
5549                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5550                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5551                 }
5552             }
5553           else
5554             {
5555               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5556             }
5557         }
5558       newConnLgth++;//+1 is for cell type
5559       connI[1]=newConnLgth;
5560     }
5561   //
5562   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5563   newConn->alloc(newConnLgth,1);
5564   int *work=newConn->getPointer();
5565   for(int i=0;i<nbOfCells;i++)
5566     {
5567       *work++=INTERP_KERNEL::NORM_POLYGON;
5568       int offset=descIndex[i];
5569       int nbOfEdges=descIndex[i+1]-offset;
5570       for(int j=0;j<nbOfEdges;j++)
5571         {
5572           bool direct=desc[offset+j]>0;
5573           int edgeId=std::abs(desc[offset+j])-1;
5574           if(direct)
5575             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5576           else
5577             {
5578               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5579               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5580               work=std::copy(it,it+nbOfSubNodes-1,work);
5581             }
5582         }
5583     }
5584   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5585   _types.clear();
5586   if(nbOfCells>0)
5587     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5588 }
5589
5590 /*!
5591  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5592  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5593  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5594  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5595  * so it can be useful to call mergeNodes() before calling this method.
5596  *  \throw If \a this->getMeshDimension() <= 1.
5597  *  \throw If the coordinates array is not set.
5598  *  \throw If the nodal connectivity of cells is not defined.
5599  */
5600 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5601 {
5602   checkFullyDefined();
5603   if(getMeshDimension()<=1)
5604     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5605   int nbOfCells=getNumberOfCells();
5606   if(nbOfCells<1)
5607     return ;
5608   int initMeshLgth=getMeshLength();
5609   int *conn=_nodal_connec->getPointer();
5610   int *index=_nodal_connec_index->getPointer();
5611   int posOfCurCell=0;
5612   int newPos=0;
5613   int lgthOfCurCell;
5614   for(int i=0;i<nbOfCells;i++)
5615     {
5616       lgthOfCurCell=index[i+1]-posOfCurCell;
5617       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5618       int newLgth;
5619       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5620                                                                                                      conn+newPos+1,newLgth);
5621       conn[newPos]=newType;
5622       newPos+=newLgth+1;
5623       posOfCurCell=index[i+1];
5624       index[i+1]=newPos;
5625     }
5626   if(newPos!=initMeshLgth)
5627     _nodal_connec->reAlloc(newPos);
5628   computeTypes();
5629 }
5630
5631 /*!
5632  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5633  * A cell is considered to be oriented correctly if an angle between its
5634  * normal vector and a given vector is less than \c PI / \c 2.
5635  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5636  *         cells. 
5637  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5638  *         checked.
5639  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5640  *         is not cleared before filling in.
5641  *  \throw If \a this->getMeshDimension() != 2.
5642  *  \throw If \a this->getSpaceDimension() != 3.
5643  *
5644  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5645  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5646  */
5647 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5648 {
5649   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5650     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5651   int nbOfCells=getNumberOfCells();
5652   const int *conn=_nodal_connec->getConstPointer();
5653   const int *connI=_nodal_connec_index->getConstPointer();
5654   const double *coordsPtr=_coords->getConstPointer();
5655   for(int i=0;i<nbOfCells;i++)
5656     {
5657       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5658       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5659         {
5660           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5661           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5662             cells.push_back(i);
5663         }
5664     }
5665 }
5666
5667 /*!
5668  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5669  * considered to be oriented correctly if an angle between its normal vector and a
5670  * given vector is less than \c PI / \c 2. 
5671  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5672  *         cells. 
5673  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5674  *         checked.
5675  *  \throw If \a this->getMeshDimension() != 2.
5676  *  \throw If \a this->getSpaceDimension() != 3.
5677  *
5678  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5679  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5680  */
5681 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5682 {
5683   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5684     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5685   int nbOfCells=getNumberOfCells();
5686   int *conn=_nodal_connec->getPointer();
5687   const int *connI=_nodal_connec_index->getConstPointer();
5688   const double *coordsPtr=_coords->getConstPointer();
5689   bool isModified=false;
5690   for(int i=0;i<nbOfCells;i++)
5691     {
5692       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5693       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5694         {
5695           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5696           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5697             {
5698               isModified=true;
5699               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5700               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5701               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5702             }
5703         }
5704     }
5705   if(isModified)
5706     _nodal_connec->declareAsNew();
5707   updateTime();
5708 }
5709
5710 /*!
5711  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5712  * oriented facets. The normal vector of the facet should point out of the cell.
5713  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5714  *         is not cleared before filling in.
5715  *  \throw If \a this->getMeshDimension() != 3.
5716  *  \throw If \a this->getSpaceDimension() != 3.
5717  *  \throw If the coordinates array is not set.
5718  *  \throw If the nodal connectivity of cells is not defined.
5719  *
5720  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5721  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5722  */
5723 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5724 {
5725   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5726     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5727   int nbOfCells=getNumberOfCells();
5728   const int *conn=_nodal_connec->getConstPointer();
5729   const int *connI=_nodal_connec_index->getConstPointer();
5730   const double *coordsPtr=_coords->getConstPointer();
5731   for(int i=0;i<nbOfCells;i++)
5732     {
5733       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5734       if(type==INTERP_KERNEL::NORM_POLYHED)
5735         {
5736           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5737             cells.push_back(i);
5738         }
5739     }
5740 }
5741
5742 /*!
5743  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5744  * out of the cell. 
5745  *  \throw If \a this->getMeshDimension() != 3.
5746  *  \throw If \a this->getSpaceDimension() != 3.
5747  *  \throw If the coordinates array is not set.
5748  *  \throw If the nodal connectivity of cells is not defined.
5749  *  \throw If the reparation fails.
5750  *
5751  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5752  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5753  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5754  */
5755 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5756 {
5757   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5758     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5759   int nbOfCells=getNumberOfCells();
5760   int *conn=_nodal_connec->getPointer();
5761   const int *connI=_nodal_connec_index->getConstPointer();
5762   const double *coordsPtr=_coords->getConstPointer();
5763   for(int i=0;i<nbOfCells;i++)
5764     {
5765       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5766       if(type==INTERP_KERNEL::NORM_POLYHED)
5767         {
5768           try
5769             {
5770               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5771                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5772             }
5773           catch(INTERP_KERNEL::Exception& e)
5774             {
5775               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5776               throw INTERP_KERNEL::Exception(oss.str().c_str());
5777             }
5778         }
5779     }
5780   updateTime();
5781 }
5782
5783 /*!
5784  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5785  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5786  * according to which the first facet of the cell should be oriented to have the normal vector
5787  * pointing out of cell.
5788  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5789  *         cells. The caller is to delete this array using decrRef() as it is no more
5790  *         needed. 
5791  *  \throw If \a this->getMeshDimension() != 3.
5792  *  \throw If \a this->getSpaceDimension() != 3.
5793  *  \throw If the coordinates array is not set.
5794  *  \throw If the nodal connectivity of cells is not defined.
5795  *
5796  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5797  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5798  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5799  */
5800 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5801 {
5802   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5803   if(getMeshDimension()!=3)
5804     throw INTERP_KERNEL::Exception(msg);
5805   int spaceDim=getSpaceDimension();
5806   if(spaceDim!=3)
5807     throw INTERP_KERNEL::Exception(msg);
5808   //
5809   int nbOfCells=getNumberOfCells();
5810   int *conn=_nodal_connec->getPointer();
5811   const int *connI=_nodal_connec_index->getConstPointer();
5812   const double *coo=getCoords()->getConstPointer();
5813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5814   for(int i=0;i<nbOfCells;i++)
5815     {
5816       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5817       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5818         {
5819           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5820             {
5821               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5822               cells->pushBackSilent(i);
5823             }
5824         }
5825     }
5826   return cells.retn();
5827 }
5828
5829 /*!
5830  * This method is a faster method to correct orientation of all 3D cells in \a this.
5831  * This method works only if \a this is a 3D mesh, that is to say a mesh with mesh dimension 3 and a space dimension 3.
5832  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5833  * 
5834  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5835  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5836  */
5837 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5838 {
5839   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5840     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5841   int nbOfCells=getNumberOfCells();
5842   int *conn=_nodal_connec->getPointer();
5843   const int *connI=_nodal_connec_index->getConstPointer();
5844   const double *coordsPtr=_coords->getConstPointer();
5845   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5846   for(int i=0;i<nbOfCells;i++)
5847     {
5848       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5849       switch(type)
5850         {
5851         case INTERP_KERNEL::NORM_TETRA4:
5852           {
5853             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5854               {
5855                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5856                 ret->pushBackSilent(i);
5857               }
5858             break;
5859           }
5860         case INTERP_KERNEL::NORM_PYRA5:
5861           {
5862             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5863               {
5864                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5865                 ret->pushBackSilent(i);
5866               }
5867             break;
5868           }
5869         case INTERP_KERNEL::NORM_PENTA6:
5870         case INTERP_KERNEL::NORM_HEXA8:
5871         case INTERP_KERNEL::NORM_HEXGP12:
5872           {
5873             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5874               {
5875                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5876                 ret->pushBackSilent(i);
5877               }
5878             break;
5879           }
5880         case INTERP_KERNEL::NORM_POLYHED:
5881           {
5882             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5883               {
5884                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5885                 ret->pushBackSilent(i);
5886               }
5887             break;
5888           }
5889         default:
5890           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orientCorrectly3DCells : Your mesh contains type of cell not supported yet ! send mail to anthony.geay@cea.fr to add it !");
5891         }
5892     }
5893   updateTime();
5894   return ret.retn();
5895 }
5896
5897 /*!
5898  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5899  * If it is not the case an exception will be thrown.
5900  * This method is fast because the first cell of \a this is used to compute the plane.
5901  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5902  * \param pos output of size at least 3 used to store a point owned of searched plane.
5903  */
5904 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5905 {
5906   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5907     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5908   const int *conn=_nodal_connec->getConstPointer();
5909   const int *connI=_nodal_connec_index->getConstPointer();
5910   const double *coordsPtr=_coords->getConstPointer();
5911   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5912   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5913 }
5914
5915 /*!
5916  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5917  * cells. Currently cells of the following types are treated:
5918  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5919  * For a cell of other type an exception is thrown.
5920  * Space dimension of a 2D mesh can be either 2 or 3.
5921  * The Edge Ratio of a cell \f$t\f$ is: 
5922  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5923  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5924  *  the smallest edge lengths of \f$t\f$.
5925  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5926  *          cells and one time, lying on \a this mesh. The caller is to delete this
5927  *          field using decrRef() as it is no more needed. 
5928  *  \throw If the coordinates array is not set.
5929  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5930  *  \throw If the connectivity data array has more than one component.
5931  *  \throw If the connectivity data array has a named component.
5932  *  \throw If the connectivity index data array has more than one component.
5933  *  \throw If the connectivity index data array has a named component.
5934  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5935  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5936  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5937  */
5938 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5939 {
5940   checkCoherency();
5941   int spaceDim=getSpaceDimension();
5942   int meshDim=getMeshDimension();
5943   if(spaceDim!=2 && spaceDim!=3)
5944     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5945   if(meshDim!=2 && meshDim!=3)
5946     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5947   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5948   ret->setMesh(this);
5949   int nbOfCells=getNumberOfCells();
5950   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5951   arr->alloc(nbOfCells,1);
5952   double *pt=arr->getPointer();
5953   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5954   const int *conn=_nodal_connec->getConstPointer();
5955   const int *connI=_nodal_connec_index->getConstPointer();
5956   const double *coo=_coords->getConstPointer();
5957   double tmp[12];
5958   for(int i=0;i<nbOfCells;i++,pt++)
5959     {
5960       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5961       switch(t)
5962         {
5963           case INTERP_KERNEL::NORM_TRI3:
5964             {
5965               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5966               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5967               break;
5968             }
5969           case INTERP_KERNEL::NORM_QUAD4:
5970             {
5971               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5972               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5973               break;
5974             }
5975           case INTERP_KERNEL::NORM_TETRA4:
5976             {
5977               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5978               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5979               break;
5980             }
5981         default:
5982           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5983         }
5984       conn+=connI[i+1]-connI[i];
5985     }
5986   ret->setName("EdgeRatio");
5987   ret->synchronizeTimeWithSupport();
5988   return ret.retn();
5989 }
5990
5991 /*!
5992  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5993  * cells. Currently cells of the following types are treated:
5994  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5995  * For a cell of other type an exception is thrown.
5996  * Space dimension of a 2D mesh can be either 2 or 3.
5997  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5998  *          cells and one time, lying on \a this mesh. The caller is to delete this
5999  *          field using decrRef() as it is no more needed. 
6000  *  \throw If the coordinates array is not set.
6001  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6002  *  \throw If the connectivity data array has more than one component.
6003  *  \throw If the connectivity data array has a named component.
6004  *  \throw If the connectivity index data array has more than one component.
6005  *  \throw If the connectivity index data array has a named component.
6006  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6007  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6008  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6009  */
6010 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6011 {
6012   checkCoherency();
6013   int spaceDim=getSpaceDimension();
6014   int meshDim=getMeshDimension();
6015   if(spaceDim!=2 && spaceDim!=3)
6016     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6017   if(meshDim!=2 && meshDim!=3)
6018     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6019   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6020   ret->setMesh(this);
6021   int nbOfCells=getNumberOfCells();
6022   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6023   arr->alloc(nbOfCells,1);
6024   double *pt=arr->getPointer();
6025   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6026   const int *conn=_nodal_connec->getConstPointer();
6027   const int *connI=_nodal_connec_index->getConstPointer();
6028   const double *coo=_coords->getConstPointer();
6029   double tmp[12];
6030   for(int i=0;i<nbOfCells;i++,pt++)
6031     {
6032       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6033       switch(t)
6034         {
6035           case INTERP_KERNEL::NORM_TRI3:
6036             {
6037               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6038               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6039               break;
6040             }
6041           case INTERP_KERNEL::NORM_QUAD4:
6042             {
6043               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6044               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6045               break;
6046             }
6047           case INTERP_KERNEL::NORM_TETRA4:
6048             {
6049               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6050               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6051               break;
6052             }
6053         default:
6054           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6055         }
6056       conn+=connI[i+1]-connI[i];
6057     }
6058   ret->setName("AspectRatio");
6059   ret->synchronizeTimeWithSupport();
6060   return ret.retn();
6061 }
6062
6063 /*!
6064  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6065  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6066  * treated: INTERP_KERNEL::NORM_QUAD4.
6067  * For a cell of other type an exception is thrown.
6068  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6069  *          cells and one time, lying on \a this mesh. The caller is to delete this
6070  *          field using decrRef() as it is no more needed. 
6071  *  \throw If the coordinates array is not set.
6072  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6073  *  \throw If the connectivity data array has more than one component.
6074  *  \throw If the connectivity data array has a named component.
6075  *  \throw If the connectivity index data array has more than one component.
6076  *  \throw If the connectivity index data array has a named component.
6077  *  \throw If \a this->getMeshDimension() != 2.
6078  *  \throw If \a this->getSpaceDimension() != 3.
6079  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6080  */
6081 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6082 {
6083   checkCoherency();
6084   int spaceDim=getSpaceDimension();
6085   int meshDim=getMeshDimension();
6086   if(spaceDim!=3)
6087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6088   if(meshDim!=2)
6089     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6090   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6091   ret->setMesh(this);
6092   int nbOfCells=getNumberOfCells();
6093   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6094   arr->alloc(nbOfCells,1);
6095   double *pt=arr->getPointer();
6096   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6097   const int *conn=_nodal_connec->getConstPointer();
6098   const int *connI=_nodal_connec_index->getConstPointer();
6099   const double *coo=_coords->getConstPointer();
6100   double tmp[12];
6101   for(int i=0;i<nbOfCells;i++,pt++)
6102     {
6103       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6104       switch(t)
6105         {
6106           case INTERP_KERNEL::NORM_QUAD4:
6107             {
6108               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6109               *pt=INTERP_KERNEL::quadWarp(tmp);
6110               break;
6111             }
6112         default:
6113           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6114         }
6115       conn+=connI[i+1]-connI[i];
6116     }
6117   ret->setName("Warp");
6118   ret->synchronizeTimeWithSupport();
6119   return ret.retn();
6120 }
6121
6122
6123 /*!
6124  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6125  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6126  * treated: INTERP_KERNEL::NORM_QUAD4.
6127  * For a cell of other type an exception is thrown.
6128  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6129  *          cells and one time, lying on \a this mesh. The caller is to delete this
6130  *          field using decrRef() as it is no more needed. 
6131  *  \throw If the coordinates array is not set.
6132  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6133  *  \throw If the connectivity data array has more than one component.
6134  *  \throw If the connectivity data array has a named component.
6135  *  \throw If the connectivity index data array has more than one component.
6136  *  \throw If the connectivity index data array has a named component.
6137  *  \throw If \a this->getMeshDimension() != 2.
6138  *  \throw If \a this->getSpaceDimension() != 3.
6139  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6140  */
6141 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6142 {
6143   checkCoherency();
6144   int spaceDim=getSpaceDimension();
6145   int meshDim=getMeshDimension();
6146   if(spaceDim!=3)
6147     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6148   if(meshDim!=2)
6149     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6150   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6151   ret->setMesh(this);
6152   int nbOfCells=getNumberOfCells();
6153   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6154   arr->alloc(nbOfCells,1);
6155   double *pt=arr->getPointer();
6156   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6157   const int *conn=_nodal_connec->getConstPointer();
6158   const int *connI=_nodal_connec_index->getConstPointer();
6159   const double *coo=_coords->getConstPointer();
6160   double tmp[12];
6161   for(int i=0;i<nbOfCells;i++,pt++)
6162     {
6163       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6164       switch(t)
6165         {
6166           case INTERP_KERNEL::NORM_QUAD4:
6167             {
6168               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6169               *pt=INTERP_KERNEL::quadSkew(tmp);
6170               break;
6171             }
6172         default:
6173           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6174         }
6175       conn+=connI[i+1]-connI[i];
6176     }
6177   ret->setName("Skew");
6178   ret->synchronizeTimeWithSupport();
6179   return ret.retn();
6180 }
6181
6182 /*!
6183  * This method aggregate the bbox of each cell and put it into bbox parameter.
6184  * 
6185  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6186  * 
6187  * \throw If \a this is not fully set (coordinates and connectivity).
6188  * \throw If a cell in \a this has no valid nodeId.
6189  */
6190 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree() const
6191 {
6192   checkFullyDefined();
6193   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6194   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6195   double *bbox(ret->getPointer());
6196   for(int i=0;i<nbOfCells*spaceDim;i++)
6197     {
6198       bbox[2*i]=std::numeric_limits<double>::max();
6199       bbox[2*i+1]=-std::numeric_limits<double>::max();
6200     }
6201   const double *coordsPtr(_coords->getConstPointer());
6202   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6203   for(int i=0;i<nbOfCells;i++)
6204     {
6205       int offset=connI[i]+1;
6206       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6207       for(int j=0;j<nbOfNodesForCell;j++)
6208         {
6209           int nodeId=conn[offset+j];
6210           if(nodeId>=0 && nodeId<nbOfNodes)
6211             {
6212               for(int k=0;k<spaceDim;k++)
6213                 {
6214                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6215                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6216                 }
6217               kk++;
6218             }
6219         }
6220       if(kk==0)
6221         {
6222           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6223           throw INTERP_KERNEL::Exception(oss.str().c_str());
6224         }
6225     }
6226   return ret.retn();
6227 }
6228
6229 /// @cond INTERNAL
6230
6231 namespace ParaMEDMEMImpl
6232 {
6233   class ConnReader
6234   {
6235   public:
6236     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6237     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6238   private:
6239     const int *_conn;
6240     int _val;
6241   };
6242
6243   class ConnReader2
6244   {
6245   public:
6246     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6247     bool operator() (const int& pos) { return _conn[pos]==_val; }
6248   private:
6249     const int *_conn;
6250     int _val;
6251   };
6252 }
6253
6254 /// @endcond
6255
6256 /*!
6257  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6258  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6259  * \a this is composed in cell types.
6260  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6261  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6262  * This parameter is kept only for compatibility with other methode listed above.
6263  */
6264 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6265 {
6266   checkConnectivityFullyDefined();
6267   const int *conn=_nodal_connec->getConstPointer();
6268   const int *connI=_nodal_connec_index->getConstPointer();
6269   const int *work=connI;
6270   int nbOfCells=getNumberOfCells();
6271   std::size_t n=getAllTypes().size();
6272   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6273   std::set<INTERP_KERNEL::NormalizedCellType> types;
6274   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6275     {
6276       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6277       if(types.find(typ)!=types.end())
6278         {
6279           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6280           oss << " is not contiguous !";
6281           throw INTERP_KERNEL::Exception(oss.str().c_str());
6282         }
6283       types.insert(typ);
6284       ret[3*i]=typ;
6285       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6286       ret[3*i+1]=(int)std::distance(work,work2);
6287       work=work2;
6288     }
6289   return ret;
6290 }
6291
6292 /*!
6293  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6294  * only for types cell, type node is not managed.
6295  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6296  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6297  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6298  * If 2 or more same geometric type is in \a code and exception is thrown too.
6299  *
6300  * This method firstly checks
6301  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6302  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6303  * an exception is thrown too.
6304  * 
6305  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6306  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6307  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6308  */
6309 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6310 {
6311   if(code.empty())
6312     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6313   std::size_t sz=code.size();
6314   std::size_t n=sz/3;
6315   if(sz%3!=0)
6316     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6317   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6318   int nb=0;
6319   bool isNoPflUsed=true;
6320   for(std::size_t i=0;i<n;i++)
6321     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6322       {
6323         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6324         nb+=code[3*i+1];
6325         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6326           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6327         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6328       }
6329   if(types.size()!=n)
6330     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6331   if(isNoPflUsed)
6332     {
6333       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6334         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6335       if(types.size()==_types.size())
6336         return 0;
6337     }
6338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6339   ret->alloc(nb,1);
6340   int *retPtr=ret->getPointer();
6341   const int *connI=_nodal_connec_index->getConstPointer();
6342   const int *conn=_nodal_connec->getConstPointer();
6343   int nbOfCells=getNumberOfCells();
6344   const int *i=connI;
6345   int kk=0;
6346   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6347     {
6348       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6349       int offset=(int)std::distance(connI,i);
6350       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6351       int nbOfCellsOfCurType=(int)std::distance(i,j);
6352       if(code[3*kk+2]==-1)
6353         for(int k=0;k<nbOfCellsOfCurType;k++)
6354           *retPtr++=k+offset;
6355       else
6356         {
6357           int idInIdsPerType=code[3*kk+2];
6358           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6359             {
6360               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6361               if(zePfl)
6362                 {
6363                   zePfl->checkAllocated();
6364                   if(zePfl->getNumberOfComponents()==1)
6365                     {
6366                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6367                         {
6368                           if(*k>=0 && *k<nbOfCellsOfCurType)
6369                             *retPtr=(*k)+offset;
6370                           else
6371                             {
6372                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6373                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6374                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6375                             }
6376                         }
6377                     }
6378                   else
6379                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6380                 }
6381               else
6382                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6383             }
6384           else
6385             {
6386               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6387               oss << " should be in [0," << idsPerType.size() << ") !";
6388               throw INTERP_KERNEL::Exception(oss.str().c_str());
6389             }
6390         }
6391       i=j;
6392     }
6393   return ret.retn();
6394 }
6395
6396 /*!
6397  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6398  * 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.
6399  * 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.
6400  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6401  * 
6402  * \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.
6403  * \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,
6404  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6405  * \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.
6406  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6407  * \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
6408  */
6409 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6410 {
6411   if(!profile)
6412     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6413   if(profile->getNumberOfComponents()!=1)
6414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6415   checkConnectivityFullyDefined();
6416   const int *conn=_nodal_connec->getConstPointer();
6417   const int *connI=_nodal_connec_index->getConstPointer();
6418   int nbOfCells=getNumberOfCells();
6419   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6420   std::vector<int> typeRangeVals(1);
6421   for(const int *i=connI;i!=connI+nbOfCells;)
6422     {
6423       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6424       if(std::find(types.begin(),types.end(),curType)!=types.end())
6425         {
6426           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6427         }
6428       types.push_back(curType);
6429       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6430       typeRangeVals.push_back((int)std::distance(connI,i));
6431     }
6432   //
6433   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6434   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6435   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6436   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6437   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6438   //
6439   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6440   code.resize(3*nbOfCastsFinal);
6441   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6442   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6443   for(int i=0;i<nbOfCastsFinal;i++)
6444     {
6445       int castId=castsPresent->getIJ(i,0);
6446       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6447       idsInPflPerType2.push_back(tmp3);
6448       code[3*i]=(int)types[castId];
6449       code[3*i+1]=tmp3->getNumberOfTuples();
6450       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6451       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6452         {
6453           tmp4->copyStringInfoFrom(*profile);
6454           idsPerType2.push_back(tmp4);
6455           code[3*i+2]=(int)idsPerType2.size()-1;
6456         }
6457       else
6458         {
6459           code[3*i+2]=-1;
6460         }
6461     }
6462   std::size_t sz2=idsInPflPerType2.size();
6463   idsInPflPerType.resize(sz2);
6464   for(std::size_t i=0;i<sz2;i++)
6465     {
6466       DataArrayInt *locDa=idsInPflPerType2[i];
6467       locDa->incrRef();
6468       idsInPflPerType[i]=locDa;
6469     }
6470   std::size_t sz=idsPerType2.size();
6471   idsPerType.resize(sz);
6472   for(std::size_t i=0;i<sz;i++)
6473     {
6474       DataArrayInt *locDa=idsPerType2[i];
6475       locDa->incrRef();
6476       idsPerType[i]=locDa;
6477     }
6478 }
6479
6480 /*!
6481  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6482  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6483  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6484  * 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.
6485  */
6486 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6487 {
6488   checkFullyDefined();
6489   nM1LevMesh->checkFullyDefined();
6490   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6491     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6492   if(_coords!=nM1LevMesh->getCoords())
6493     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6494   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6495   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6496   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6497   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6498   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6499   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6500   tmp->setConnectivity(tmp0,tmp1);
6501   tmp->renumberCells(ret0->getConstPointer(),false);
6502   revDesc=tmp->getNodalConnectivity();
6503   revDescIndx=tmp->getNodalConnectivityIndex();
6504   DataArrayInt *ret=0;
6505   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6506     {
6507       int tmp2;
6508       ret->getMaxValue(tmp2);
6509       ret->decrRef();
6510       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6511       throw INTERP_KERNEL::Exception(oss.str().c_str());
6512     }
6513   nM1LevMeshIds=ret;
6514   //
6515   revDesc->incrRef();
6516   revDescIndx->incrRef();
6517   ret1->incrRef();
6518   ret0->incrRef();
6519   meshnM1Old2New=ret0;
6520   return ret1;
6521 }
6522
6523 /*!
6524  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6525  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6526  * in "Old to New" mode.
6527  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6528  *          this array using decrRef() as it is no more needed.
6529  *  \throw If the nodal connectivity of cells is not defined.
6530  */
6531 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6532 {
6533   checkConnectivityFullyDefined();
6534   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6535   renumberCells(ret->getConstPointer(),false);
6536   return ret.retn();
6537 }
6538
6539 /*!
6540  * This methods checks that cells are sorted by their types.
6541  * This method makes asumption (no check) that connectivity is correctly set before calling.
6542  */
6543 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6544 {
6545   checkFullyDefined();
6546   const int *conn=_nodal_connec->getConstPointer();
6547   const int *connI=_nodal_connec_index->getConstPointer();
6548   int nbOfCells=getNumberOfCells();
6549   std::set<INTERP_KERNEL::NormalizedCellType> types;
6550   for(const int *i=connI;i!=connI+nbOfCells;)
6551     {
6552       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6553       if(types.find(curType)!=types.end())
6554         return false;
6555       types.insert(curType);
6556       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6557     }
6558   return true;
6559 }
6560
6561 /*!
6562  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6563  * The geometric type order is specified by MED file.
6564  * 
6565  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6566  */
6567 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6568 {
6569   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6570 }
6571
6572 /*!
6573  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6574  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6575  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6576  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6577  */
6578 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6579 {
6580   checkFullyDefined();
6581   const int *conn=_nodal_connec->getConstPointer();
6582   const int *connI=_nodal_connec_index->getConstPointer();
6583   int nbOfCells=getNumberOfCells();
6584   if(nbOfCells==0)
6585     return true;
6586   int lastPos=-1;
6587   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6588   for(const int *i=connI;i!=connI+nbOfCells;)
6589     {
6590       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6591       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6592       if(isTypeExists!=orderEnd)
6593         {
6594           int pos=(int)std::distance(orderBg,isTypeExists);
6595           if(pos<=lastPos)
6596             return false;
6597           lastPos=pos;
6598           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6599         }
6600       else
6601         {
6602           if(sg.find(curType)==sg.end())
6603             {
6604               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6605               sg.insert(curType);
6606             }
6607           else
6608             return false;
6609         }
6610     }
6611   return true;
6612 }
6613
6614 /*!
6615  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6616  * 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
6617  * 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'.
6618  */
6619 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6620 {
6621   checkConnectivityFullyDefined();
6622   int nbOfCells=getNumberOfCells();
6623   const int *conn=_nodal_connec->getConstPointer();
6624   const int *connI=_nodal_connec_index->getConstPointer();
6625   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6626   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6627   tmpa->alloc(nbOfCells,1);
6628   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6629   tmpb->fillWithZero();
6630   int *tmp=tmpa->getPointer();
6631   int *tmp2=tmpb->getPointer();
6632   for(const int *i=connI;i!=connI+nbOfCells;i++)
6633     {
6634       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6635       if(where!=orderEnd)
6636         {
6637           int pos=(int)std::distance(orderBg,where);
6638           tmp2[pos]++;
6639           tmp[std::distance(connI,i)]=pos;
6640         }
6641       else
6642         {
6643           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6644           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6645           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6646           throw INTERP_KERNEL::Exception(oss.str().c_str());
6647         }
6648     }
6649   nbPerType=tmpb.retn();
6650   return tmpa.retn();
6651 }
6652
6653 /*!
6654  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6655  *
6656  * \return a new object containing the old to new correspondance.
6657  *
6658  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6659  */
6660 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6661 {
6662   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6663 }
6664
6665 /*!
6666  * 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.
6667  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6668  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6669  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6670  */
6671 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6672 {
6673   DataArrayInt *nbPerType=0;
6674   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6675   nbPerType->decrRef();
6676   return tmpa->buildPermArrPerLevel();
6677 }
6678
6679 /*!
6680  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6681  * The number of cells remains unchanged after the call of this method.
6682  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6683  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6684  *
6685  * \return the array giving the correspondance old to new.
6686  */
6687 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6688 {
6689   checkFullyDefined();
6690   computeTypes();
6691   const int *conn=_nodal_connec->getConstPointer();
6692   const int *connI=_nodal_connec_index->getConstPointer();
6693   int nbOfCells=getNumberOfCells();
6694   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6695   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6696     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6697       {
6698         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6699         types.push_back(curType);
6700         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6701       }
6702   DataArrayInt *ret=DataArrayInt::New();
6703   ret->alloc(nbOfCells,1);
6704   int *retPtr=ret->getPointer();
6705   std::fill(retPtr,retPtr+nbOfCells,-1);
6706   int newCellId=0;
6707   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6708     {
6709       for(const int *i=connI;i!=connI+nbOfCells;i++)
6710         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6711           retPtr[std::distance(connI,i)]=newCellId++;
6712     }
6713   renumberCells(retPtr,false);
6714   return ret;
6715 }
6716
6717 /*!
6718  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6719  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6720  * This method makes asumption that connectivity is correctly set before calling.
6721  */
6722 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6723 {
6724   checkConnectivityFullyDefined();
6725   const int *conn=_nodal_connec->getConstPointer();
6726   const int *connI=_nodal_connec_index->getConstPointer();
6727   int nbOfCells=getNumberOfCells();
6728   std::vector<MEDCouplingUMesh *> ret;
6729   for(const int *i=connI;i!=connI+nbOfCells;)
6730     {
6731       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6732       int beginCellId=(int)std::distance(connI,i);
6733       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6734       int endCellId=(int)std::distance(connI,i);
6735       int sz=endCellId-beginCellId;
6736       int *cells=new int[sz];
6737       for(int j=0;j<sz;j++)
6738         cells[j]=beginCellId+j;
6739       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6740       delete [] cells;
6741       ret.push_back(m);
6742     }
6743   return ret;
6744 }
6745
6746 /*!
6747  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6748  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6749  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6750  *
6751  * \return a newly allocated instance, that the caller must manage.
6752  * \throw If \a this contains more than one geometric type.
6753  * \throw If the nodal connectivity of \a this is not fully defined.
6754  * \throw If the internal data is not coherent.
6755  */
6756 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6757 {
6758   checkConnectivityFullyDefined();
6759     if(_types.size()!=1)
6760     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6761   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6762   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6763   ret->setCoords(getCoords());
6764   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6765   if(retC)
6766     {
6767       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6768       retC->setNodalConnectivity(c);
6769     }
6770   else
6771     {
6772       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6773       if(!retD)
6774         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6775       DataArrayInt *c=0,*ci=0;
6776       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6777       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6778       retD->setNodalConnectivity(cs,cis);
6779     }
6780   return ret.retn();
6781 }
6782
6783 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6784 {
6785   checkConnectivityFullyDefined();
6786     if(_types.size()!=1)
6787     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6788   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6789   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6790   if(cm.isDynamic())
6791     {
6792       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6793       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6794       throw INTERP_KERNEL::Exception(oss.str().c_str());
6795     }
6796   int nbCells=getNumberOfCells();
6797   int typi=(int)typ;
6798   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6799   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6800   int *outPtr=connOut->getPointer();
6801   const int *conn=_nodal_connec->begin();
6802   const int *connI=_nodal_connec_index->begin();
6803   nbNodesPerCell++;
6804   for(int i=0;i<nbCells;i++,connI++)
6805     {
6806       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6807         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6808       else
6809         {
6810           std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
6811           throw INTERP_KERNEL::Exception(oss.str().c_str());
6812         }
6813     }
6814   return connOut.retn();
6815 }
6816
6817 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6818 {
6819   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6820   checkConnectivityFullyDefined();
6821   if(_types.size()!=1)
6822     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6823   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6824   if(lgth<nbCells)
6825     throw INTERP_KERNEL::Exception(msg0);
6826   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6827   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6828   int *cp(c->getPointer()),*cip(ci->getPointer());
6829   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6830   cip[0]=0;
6831   for(int i=0;i<nbCells;i++,cip++,incip++)
6832     {
6833       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6834       int delta(stop-strt);
6835       if(delta>=1)
6836         {
6837           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6838             cp=std::copy(incp+strt,incp+stop,cp);
6839           else
6840             throw INTERP_KERNEL::Exception(msg0);
6841         }
6842       else
6843         throw INTERP_KERNEL::Exception(msg0);
6844       cip[1]=cip[0]+delta;
6845     }
6846   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6847 }
6848
6849 /*!
6850  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6851  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6852  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6853  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6854  * are not used here to avoid the build of big permutation array.
6855  *
6856  * \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
6857  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6858  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6859  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6860  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6861  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6862  * \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
6863  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6864  */
6865 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6866                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6867                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6868 {
6869   std::vector<const MEDCouplingUMesh *> ms2;
6870   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6871     if(*it)
6872       {
6873         (*it)->checkConnectivityFullyDefined();
6874         ms2.push_back(*it);
6875       }
6876   if(ms2.empty())
6877     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6878   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6879   int meshDim=ms2[0]->getMeshDimension();
6880   std::vector<const MEDCouplingUMesh *> m1ssm;
6881   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6882   //
6883   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6884   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6885   int fake=0,rk=0;
6886   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6887   ret1->alloc(0,1); ret2->alloc(0,1);
6888   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6889     {
6890       if(meshDim!=(*it)->getMeshDimension())
6891         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6892       if(refCoo!=(*it)->getCoords())
6893         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6894       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6895       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6896       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6897       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6898         {
6899           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6900           m1ssmSingleAuto.push_back(singleCell);
6901           m1ssmSingle.push_back(singleCell);
6902           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6903         }
6904     }
6905   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6907   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6908   for(std::size_t i=0;i<m1ssm.size();i++)
6909     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6910   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6911   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6912   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6913   return ret0.retn();
6914 }
6915
6916 /*!
6917  * This method returns a newly created DataArrayInt instance.
6918  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6919  */
6920 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6921 {
6922   checkFullyDefined();
6923   const int *conn=_nodal_connec->getConstPointer();
6924   const int *connIndex=_nodal_connec_index->getConstPointer();
6925   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6926   for(const int *w=begin;w!=end;w++)
6927     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6928       ret->pushBackSilent(*w);
6929   return ret.retn();
6930 }
6931
6932 /*!
6933  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6934  * are in [0:getNumberOfCells())
6935  */
6936 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6937 {
6938   checkFullyDefined();
6939   const int *conn=_nodal_connec->getConstPointer();
6940   const int *connI=_nodal_connec_index->getConstPointer();
6941   int nbOfCells=getNumberOfCells();
6942   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6943   int *tmp=new int[nbOfCells];
6944   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6945     {
6946       int j=0;
6947       for(const int *i=connI;i!=connI+nbOfCells;i++)
6948         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6949           tmp[std::distance(connI,i)]=j++;
6950     }
6951   DataArrayInt *ret=DataArrayInt::New();
6952   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6953   ret->copyStringInfoFrom(*da);
6954   int *retPtr=ret->getPointer();
6955   const int *daPtr=da->getConstPointer();
6956   int nbOfElems=da->getNbOfElems();
6957   for(int k=0;k<nbOfElems;k++)
6958     retPtr[k]=tmp[daPtr[k]];
6959   delete [] tmp;
6960   return ret;
6961 }
6962
6963 /*!
6964  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6965  * This method \b works \b for mesh sorted by type.
6966  * cells whose ids is in 'idsPerGeoType' array.
6967  * This method conserves coords and name of mesh.
6968  */
6969 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6970 {
6971   std::vector<int> code=getDistributionOfTypes();
6972   std::size_t nOfTypesInThis=code.size()/3;
6973   int sz=0,szOfType=0;
6974   for(std::size_t i=0;i<nOfTypesInThis;i++)
6975     {
6976       if(code[3*i]!=type)
6977         sz+=code[3*i+1];
6978       else
6979         szOfType=code[3*i+1];
6980     }
6981   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6982     if(*work<0 || *work>=szOfType)
6983       {
6984         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6985         oss << ". It should be in [0," << szOfType << ") !";
6986         throw INTERP_KERNEL::Exception(oss.str().c_str());
6987       }
6988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6989   int *idsPtr=idsTokeep->getPointer();
6990   int offset=0;
6991   for(std::size_t i=0;i<nOfTypesInThis;i++)
6992     {
6993       if(code[3*i]!=type)
6994         for(int j=0;j<code[3*i+1];j++)
6995           *idsPtr++=offset+j;
6996       else
6997         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6998       offset+=code[3*i+1];
6999     }
7000   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7001   ret->copyTinyInfoFrom(this);
7002   return ret.retn();
7003 }
7004
7005 /*!
7006  * This method returns a vector of size 'this->getNumberOfCells()'.
7007  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7008  */
7009 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7010 {
7011   int ncell=getNumberOfCells();
7012   std::vector<bool> ret(ncell);
7013   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7014   const int *c=getNodalConnectivity()->getConstPointer();
7015   for(int i=0;i<ncell;i++)
7016     {
7017       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7018       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7019       ret[i]=cm.isQuadratic();
7020     }
7021   return ret;
7022 }
7023
7024 /*!
7025  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7026  */
7027 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7028 {
7029   if(other->getType()!=UNSTRUCTURED)
7030     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7031   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7032   return MergeUMeshes(this,otherC);
7033 }
7034
7035 /*!
7036  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7037  * computed by averaging coordinates of cell nodes, so this method is not a right
7038  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7039  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7040  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7041  *          components. The caller is to delete this array using decrRef() as it is
7042  *          no more needed.
7043  *  \throw If the coordinates array is not set.
7044  *  \throw If the nodal connectivity of cells is not defined.
7045  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7046  */
7047 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7048 {
7049   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7050   int spaceDim=getSpaceDimension();
7051   int nbOfCells=getNumberOfCells();
7052   ret->alloc(nbOfCells,spaceDim);
7053   ret->copyStringInfoFrom(*getCoords());
7054   double *ptToFill=ret->getPointer();
7055   const int *nodal=_nodal_connec->getConstPointer();
7056   const int *nodalI=_nodal_connec_index->getConstPointer();
7057   const double *coor=_coords->getConstPointer();
7058   for(int i=0;i<nbOfCells;i++)
7059     {
7060       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7061       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7062       ptToFill+=spaceDim;
7063     }
7064   return ret.retn();
7065 }
7066
7067 /*!
7068  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7069  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7070  * 
7071  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7072  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7073  * 
7074  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7075  * \throw If \a this is not fully defined (coordinates and connectivity)
7076  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7077  */
7078 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7079 {
7080   checkFullyDefined();
7081   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7082   int spaceDim=getSpaceDimension();
7083   int nbOfCells=getNumberOfCells();
7084   int nbOfNodes=getNumberOfNodes();
7085   ret->alloc(nbOfCells,spaceDim);
7086   double *ptToFill=ret->getPointer();
7087   const int *nodal=_nodal_connec->getConstPointer();
7088   const int *nodalI=_nodal_connec_index->getConstPointer();
7089   const double *coor=_coords->getConstPointer();
7090   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7091     {
7092       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7093       std::fill(ptToFill,ptToFill+spaceDim,0.);
7094       if(type!=INTERP_KERNEL::NORM_POLYHED)
7095         {
7096           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7097             {
7098               if(*conn>=0 && *conn<nbOfNodes)
7099                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7100               else
7101                 {
7102                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7103                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7104                 }
7105             }
7106           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7107           if(nbOfNodesInCell>0)
7108             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7109           else
7110             {
7111               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7112               throw INTERP_KERNEL::Exception(oss.str().c_str());
7113             }
7114         }
7115       else
7116         {
7117           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7118           s.erase(-1);
7119           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7120             {
7121               if(*it>=0 && *it<nbOfNodes)
7122                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7123               else
7124                 {
7125                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7126                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7127                 }
7128             }
7129           if(!s.empty())
7130             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7131           else
7132             {
7133               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7134               throw INTERP_KERNEL::Exception(oss.str().c_str());
7135             }
7136         }
7137     }
7138   return ret.retn();
7139 }
7140
7141 /*!
7142  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7143  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7144  * are specified via an array of cell ids. 
7145  *  \warning Validity of the specified cell ids is not checked! 
7146  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7147  *  \param [in] begin - an array of cell ids of interest.
7148  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7149  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7150  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7151  *          caller is to delete this array using decrRef() as it is no more needed. 
7152  *  \throw If the coordinates array is not set.
7153  *  \throw If the nodal connectivity of cells is not defined.
7154  *
7155  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7156  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7157  */
7158 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7159 {
7160   DataArrayDouble *ret=DataArrayDouble::New();
7161   int spaceDim=getSpaceDimension();
7162   int nbOfTuple=(int)std::distance(begin,end);
7163   ret->alloc(nbOfTuple,spaceDim);
7164   double *ptToFill=ret->getPointer();
7165   double *tmp=new double[spaceDim];
7166   const int *nodal=_nodal_connec->getConstPointer();
7167   const int *nodalI=_nodal_connec_index->getConstPointer();
7168   const double *coor=_coords->getConstPointer();
7169   for(const int *w=begin;w!=end;w++)
7170     {
7171       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7172       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7173       ptToFill+=spaceDim;
7174     }
7175   delete [] tmp;
7176   return ret;
7177 }
7178
7179 /*!
7180  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7181  * 
7182  */
7183 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7184 {
7185   if(!da)
7186     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7187   da->checkAllocated();
7188   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7189   ret->setCoords(da);
7190   int nbOfTuples=da->getNumberOfTuples();
7191   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7192   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7193   c->alloc(2*nbOfTuples,1);
7194   cI->alloc(nbOfTuples+1,1);
7195   int *cp=c->getPointer();
7196   int *cip=cI->getPointer();
7197   *cip++=0;
7198   for(int i=0;i<nbOfTuples;i++)
7199     {
7200       *cp++=INTERP_KERNEL::NORM_POINT1;
7201       *cp++=i;
7202       *cip++=2*(i+1);
7203     }
7204   ret->setConnectivity(c,cI,true);
7205   return ret.retn();
7206 }
7207 /*!
7208  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7209  * Cells and nodes of
7210  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7211  *  \param [in] mesh1 - the first mesh.
7212  *  \param [in] mesh2 - the second mesh.
7213  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7214  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7215  *          is no more needed.
7216  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7217  *  \throw If the coordinates array is not set in none of the meshes.
7218  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7219  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7220  */
7221 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7222 {
7223   std::vector<const MEDCouplingUMesh *> tmp(2);
7224   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7225   return MergeUMeshes(tmp);
7226 }
7227
7228 /*!
7229  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7230  * Cells and nodes of
7231  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7232  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7233  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7234  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7235  *          is no more needed.
7236  *  \throw If \a a.size() == 0.
7237  *  \throw If \a a[ *i* ] == NULL.
7238  *  \throw If the coordinates array is not set in none of the meshes.
7239  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7240  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7241 */
7242 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7243 {
7244   std::size_t sz=a.size();
7245   if(sz==0)
7246     return MergeUMeshesLL(a);
7247   for(std::size_t ii=0;ii<sz;ii++)
7248     if(!a[ii])
7249       {
7250         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7251         throw INTERP_KERNEL::Exception(oss.str().c_str());
7252       }
7253   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7254   std::vector< const MEDCouplingUMesh * > aa(sz);
7255   int spaceDim=-3;
7256   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7257     {
7258       const MEDCouplingUMesh *cur=a[i];
7259       const DataArrayDouble *coo=cur->getCoords();
7260       if(coo)
7261         spaceDim=coo->getNumberOfComponents();
7262     }
7263   if(spaceDim==-3)
7264     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7265   for(std::size_t i=0;i<sz;i++)
7266     {
7267       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7268       aa[i]=bb[i];
7269     }
7270   return MergeUMeshesLL(aa);
7271 }
7272
7273 /// @cond INTERNAL
7274
7275 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7276 {
7277   if(a.empty())
7278     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7279   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7280   int meshDim=(*it)->getMeshDimension();
7281   int nbOfCells=(*it)->getNumberOfCells();
7282   int meshLgth=(*it++)->getMeshLength();
7283   for(;it!=a.end();it++)
7284     {
7285       if(meshDim!=(*it)->getMeshDimension())
7286         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7287       nbOfCells+=(*it)->getNumberOfCells();
7288       meshLgth+=(*it)->getMeshLength();
7289     }
7290   std::vector<const MEDCouplingPointSet *> aps(a.size());
7291   std::copy(a.begin(),a.end(),aps.begin());
7292   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7293   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7294   ret->setCoords(pts);
7295   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7296   c->alloc(meshLgth,1);
7297   int *cPtr=c->getPointer();
7298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7299   cI->alloc(nbOfCells+1,1);
7300   int *cIPtr=cI->getPointer();
7301   *cIPtr++=0;
7302   int offset=0;
7303   int offset2=0;
7304   for(it=a.begin();it!=a.end();it++)
7305     {
7306       int curNbOfCell=(*it)->getNumberOfCells();
7307       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7308       const int *curC=(*it)->_nodal_connec->getConstPointer();
7309       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7310       for(int j=0;j<curNbOfCell;j++)
7311         {
7312           const int *src=curC+curCI[j];
7313           *cPtr++=*src++;
7314           for(;src!=curC+curCI[j+1];src++,cPtr++)
7315             {
7316               if(*src!=-1)
7317                 *cPtr=*src+offset2;
7318               else
7319                 *cPtr=-1;
7320             }
7321         }
7322       offset+=curCI[curNbOfCell];
7323       offset2+=(*it)->getNumberOfNodes();
7324     }
7325   //
7326   ret->setConnectivity(c,cI,true);
7327   return ret.retn();
7328 }
7329
7330 /// @endcond
7331
7332 /*!
7333  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7334  * dimension and sharing the node coordinates array.
7335  * All cells of the first mesh precede all cells of the second mesh
7336  * within the result mesh. 
7337  *  \param [in] mesh1 - the first mesh.
7338  *  \param [in] mesh2 - the second mesh.
7339  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7340  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7341  *          is no more needed.
7342  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7343  *  \throw If the meshes do not share the node coordinates array.
7344  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7345  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7346  */
7347 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7348 {
7349   std::vector<const MEDCouplingUMesh *> tmp(2);
7350   tmp[0]=mesh1; tmp[1]=mesh2;
7351   return MergeUMeshesOnSameCoords(tmp);
7352 }
7353
7354 /*!
7355  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7356  * dimension and sharing the node coordinates array.
7357  * All cells of the *i*-th mesh precede all cells of the
7358  * (*i*+1)-th mesh within the result mesh.
7359  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7360  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7361  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7362  *          is no more needed.
7363  *  \throw If \a a.size() == 0.
7364  *  \throw If \a a[ *i* ] == NULL.
7365  *  \throw If the meshes do not share the node coordinates array.
7366  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7367  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7368  */
7369 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7370 {
7371   if(meshes.empty())
7372     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7373   for(std::size_t ii=0;ii<meshes.size();ii++)
7374     if(!meshes[ii])
7375       {
7376         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7377         throw INTERP_KERNEL::Exception(oss.str().c_str());
7378       }
7379   const DataArrayDouble *coords=meshes.front()->getCoords();
7380   int meshDim=meshes.front()->getMeshDimension();
7381   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7382   int meshLgth=0;
7383   int meshIndexLgth=0;
7384   for(;iter!=meshes.end();iter++)
7385     {
7386       if(coords!=(*iter)->getCoords())
7387         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7388       if(meshDim!=(*iter)->getMeshDimension())
7389         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7390       meshLgth+=(*iter)->getMeshLength();
7391       meshIndexLgth+=(*iter)->getNumberOfCells();
7392     }
7393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7394   nodal->alloc(meshLgth,1);
7395   int *nodalPtr=nodal->getPointer();
7396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7397   nodalIndex->alloc(meshIndexLgth+1,1);
7398   int *nodalIndexPtr=nodalIndex->getPointer();
7399   int offset=0;
7400   for(iter=meshes.begin();iter!=meshes.end();iter++)
7401     {
7402       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7403       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7404       int nbOfCells=(*iter)->getNumberOfCells();
7405       int meshLgth2=(*iter)->getMeshLength();
7406       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7407       if(iter!=meshes.begin())
7408         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7409       else
7410         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7411       offset+=meshLgth2;
7412     }
7413   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7414   ret->setName("merge");
7415   ret->setMeshDimension(meshDim);
7416   ret->setConnectivity(nodal,nodalIndex,true);
7417   ret->setCoords(coords);
7418   return ret;
7419 }
7420
7421 /*!
7422  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7423  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7424  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7425  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7426  * New" mode are returned for each input mesh.
7427  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7428  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7429  *          valid values [0,1,2], see zipConnectivityTraducer().
7430  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7431  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7432  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7433  *          no more needed.
7434  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7435  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7436  *          is no more needed.
7437  *  \throw If \a meshes.size() == 0.
7438  *  \throw If \a meshes[ *i* ] == NULL.
7439  *  \throw If the meshes do not share the node coordinates array.
7440  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7441  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7442  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7443  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7444  */
7445 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7446 {
7447   //All checks are delegated to MergeUMeshesOnSameCoords
7448   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7449   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7450   corr.resize(meshes.size());
7451   std::size_t nbOfMeshes=meshes.size();
7452   int offset=0;
7453   const int *o2nPtr=o2n->getConstPointer();
7454   for(std::size_t i=0;i<nbOfMeshes;i++)
7455     {
7456       DataArrayInt *tmp=DataArrayInt::New();
7457       int curNbOfCells=meshes[i]->getNumberOfCells();
7458       tmp->alloc(curNbOfCells,1);
7459       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7460       offset+=curNbOfCells;
7461       tmp->setName(meshes[i]->getName().c_str());
7462       corr[i]=tmp;
7463     }
7464   return ret.retn();
7465 }
7466
7467 /*!
7468  * Makes all given meshes share the nodal connectivity array. The common connectivity
7469  * array is created by concatenating the connectivity arrays of all given meshes. All
7470  * the given meshes must be of the same space dimension but dimension of cells **can
7471  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7472  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7473  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7474  *  \param [in,out] meshes - a vector of meshes to update.
7475  *  \throw If any of \a meshes is NULL.
7476  *  \throw If the coordinates array is not set in any of \a meshes.
7477  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7478  *  \throw If \a meshes are of different space dimension.
7479  */
7480 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7481 {
7482   std::size_t sz=meshes.size();
7483   if(sz==0 || sz==1)
7484     return;
7485   std::vector< const DataArrayDouble * > coords(meshes.size());
7486   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7487   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7488     {
7489       if((*it))
7490         {
7491           (*it)->checkConnectivityFullyDefined();
7492           const DataArrayDouble *coo=(*it)->getCoords();
7493           if(coo)
7494             *it2=coo;
7495           else
7496             {
7497               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7498               oss << " has no coordinate array defined !";
7499               throw INTERP_KERNEL::Exception(oss.str().c_str());
7500             }
7501         }
7502       else
7503         {
7504           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7505           oss << " is null !";
7506           throw INTERP_KERNEL::Exception(oss.str().c_str());
7507         }
7508     }
7509   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7510   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7511   int offset=(*it)->getNumberOfNodes();
7512   (*it++)->setCoords(res);
7513   for(;it!=meshes.end();it++)
7514     {
7515       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7516       (*it)->setCoords(res);
7517       (*it)->shiftNodeNumbersInConn(offset);
7518       offset+=oldNumberOfNodes;
7519     }
7520 }
7521
7522 /*!
7523  * Merges nodes coincident with a given precision within all given meshes that share
7524  * the nodal connectivity array. The given meshes **can be of different** mesh
7525  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7526  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7527  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7528  *  \param [in,out] meshes - a vector of meshes to update.
7529  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7530  *  \throw If any of \a meshes is NULL.
7531  *  \throw If the \a meshes do not share the same node coordinates array.
7532  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7533  */
7534 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7535 {
7536   if(meshes.empty())
7537     return ;
7538   std::set<const DataArrayDouble *> s;
7539   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7540     {
7541       if(*it)
7542         s.insert((*it)->getCoords());
7543       else
7544         {
7545           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 !";
7546           throw INTERP_KERNEL::Exception(oss.str().c_str());
7547         }
7548     }
7549   if(s.size()!=1)
7550     {
7551       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 !";
7552       throw INTERP_KERNEL::Exception(oss.str().c_str());
7553     }
7554   const DataArrayDouble *coo=*(s.begin());
7555   if(!coo)
7556     return;
7557   //
7558   DataArrayInt *comm,*commI;
7559   coo->findCommonTuples(eps,-1,comm,commI);
7560   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7561   int oldNbOfNodes=coo->getNumberOfTuples();
7562   int newNbOfNodes;
7563   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7564   if(oldNbOfNodes==newNbOfNodes)
7565     return ;
7566   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7567   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7568     {
7569       (*it)->renumberNodesInConn(o2n->getConstPointer());
7570       (*it)->setCoords(newCoords);
7571     } 
7572 }
7573
7574 /*!
7575  * 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.
7576  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7577  * \param isQuad specifies the policy of connectivity.
7578  * @ret in/out parameter in which the result will be append
7579  */
7580 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7581 {
7582   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7583   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7584   ret.push_back(cm.getExtrudedType());
7585   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7586   switch(flatType)
7587     {
7588     case INTERP_KERNEL::NORM_POINT1:
7589       {
7590         ret.push_back(connBg[1]);
7591         ret.push_back(connBg[1]+nbOfNodesPerLev);
7592         break;
7593       }
7594     case INTERP_KERNEL::NORM_SEG2:
7595       {
7596         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7597         ret.insert(ret.end(),conn,conn+4);
7598         break;
7599       }
7600     case INTERP_KERNEL::NORM_SEG3:
7601       {
7602         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7603         ret.insert(ret.end(),conn,conn+8);
7604         break;
7605       }
7606     case INTERP_KERNEL::NORM_QUAD4:
7607       {
7608         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7609         ret.insert(ret.end(),conn,conn+8);
7610         break;
7611       }
7612     case INTERP_KERNEL::NORM_TRI3:
7613       {
7614         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7615         ret.insert(ret.end(),conn,conn+6);
7616         break;
7617       }
7618     case INTERP_KERNEL::NORM_TRI6:
7619       {
7620         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,
7621                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7622         ret.insert(ret.end(),conn,conn+15);
7623         break;
7624       }
7625     case INTERP_KERNEL::NORM_QUAD8:
7626       {
7627         int conn[20]={
7628           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7629           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7630           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7631         };
7632         ret.insert(ret.end(),conn,conn+20);
7633         break;
7634       }
7635     case INTERP_KERNEL::NORM_POLYGON:
7636       {
7637         std::back_insert_iterator< std::vector<int> > ii(ret);
7638         std::copy(connBg+1,connEnd,ii);
7639         *ii++=-1;
7640         std::reverse_iterator<const int *> rConnBg(connEnd);
7641         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7642         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7643         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7644         for(std::size_t i=0;i<nbOfRadFaces;i++)
7645           {
7646             *ii++=-1;
7647             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7648             std::copy(conn,conn+4,ii);
7649           }
7650         break;
7651       }
7652     default:
7653       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7654     }
7655 }
7656
7657 /*!
7658  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7659  */
7660 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7661 {
7662   double v[3]={0.,0.,0.};
7663   std::size_t sz=std::distance(begin,end);
7664   if(isQuadratic)
7665     sz/=2;
7666   for(std::size_t i=0;i<sz;i++)
7667     {
7668       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];
7669       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7670       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7671     }
7672   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7673 }
7674
7675 /*!
7676  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7677  */
7678 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7679 {
7680   std::vector<std::pair<int,int> > edges;
7681   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7682   const int *bgFace=begin;
7683   for(std::size_t i=0;i<nbOfFaces;i++)
7684     {
7685       const int *endFace=std::find(bgFace+1,end,-1);
7686       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7687       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7688         {
7689           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7690           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7691             return false;
7692           edges.push_back(p1);
7693         }
7694       bgFace=endFace+1;
7695     }
7696   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7697 }
7698
7699 /*!
7700  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7701  */
7702 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7703 {
7704   double vec0[3],vec1[3];
7705   std::size_t sz=std::distance(begin,end);
7706   if(sz%2!=0)
7707     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7708   int nbOfNodes=(int)sz/2;
7709   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7710   const double *pt0=coords+3*begin[0];
7711   const double *pt1=coords+3*begin[nbOfNodes];
7712   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7713   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7714 }
7715
7716 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7717 {
7718   std::size_t sz=std::distance(begin,end);
7719   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7720   std::size_t nbOfNodes(sz/2);
7721   std::copy(begin,end,(int *)tmp);
7722   for(std::size_t j=1;j<nbOfNodes;j++)
7723     {
7724       begin[j]=tmp[nbOfNodes-j];
7725       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7726     }
7727 }
7728
7729 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7730 {
7731   std::size_t sz=std::distance(begin,end);
7732   if(sz!=4)
7733     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7734   double vec0[3],vec1[3];
7735   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7736   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]; 
7737   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;
7738 }
7739
7740 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7741 {
7742   std::size_t sz=std::distance(begin,end);
7743   if(sz!=5)
7744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7745   double vec0[3];
7746   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7747   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7748   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7749 }
7750
7751 /*!
7752  * 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 ) 
7753  * 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
7754  * a 2D space.
7755  *
7756  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7757  * \param [in] coords the coordinates with nb of components exactly equal to 3
7758  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7759  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7760  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7761  */
7762 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7763 {
7764   int nbFaces=std::count(begin+1,end,-1)+1;
7765   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7766   double *vPtr=v->getPointer();
7767   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7768   double *pPtr=p->getPointer();
7769   const int *stFaceConn=begin+1;
7770   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7771     {
7772       const int *endFaceConn=std::find(stFaceConn,end,-1);
7773       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7774       stFaceConn=endFaceConn+1;
7775     }
7776   pPtr=p->getPointer(); vPtr=v->getPointer();
7777   DataArrayInt *comm1=0,*commI1=0;
7778   v->findCommonTuples(eps,-1,comm1,commI1);
7779   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7780   const int *comm1Ptr=comm1->getConstPointer();
7781   const int *commI1Ptr=commI1->getConstPointer();
7782   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7783   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7784   //
7785   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7786   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7787   mm->finishInsertingCells();
7788   //
7789   for(int i=0;i<nbOfGrps1;i++)
7790     {
7791       int vecId=comm1Ptr[commI1Ptr[i]];
7792       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7793       DataArrayInt *comm2=0,*commI2=0;
7794       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7795       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7796       const int *comm2Ptr=comm2->getConstPointer();
7797       const int *commI2Ptr=commI2->getConstPointer();
7798       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7799       for(int j=0;j<nbOfGrps2;j++)
7800         {
7801           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7802             {
7803               res->insertAtTheEnd(begin,end);
7804               res->pushBackSilent(-1);
7805             }
7806           else
7807             {
7808               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7809               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7810               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7811               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7812               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7813               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7814               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7815               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7816               const int *idsNodePtr=idsNode->getConstPointer();
7817               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];
7818               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7819               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7820               if(std::abs(norm)>eps)
7821                 {
7822                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7823                   mm3->rotate(center,vec,angle);
7824                 }
7825               mm3->changeSpaceDimension(2);
7826               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7827               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7828               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7829               int nbOfCells=mm4->getNumberOfCells();
7830               for(int k=0;k<nbOfCells;k++)
7831                 {
7832                   int l=0;
7833                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7834                     res->pushBackSilent(idsNodePtr[*work]);
7835                   res->pushBackSilent(-1);
7836                 }
7837             }
7838         }
7839     }
7840   res->popBackSilent();
7841 }
7842
7843 /*!
7844  * 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
7845  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7846  * 
7847  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7848  * \param [in] coords coordinates expected to have 3 components.
7849  * \param [in] begin start of the nodal connectivity of the face.
7850  * \param [in] end end of the nodal connectivity (excluded) of the face.
7851  * \param [out] v the normalized vector of size 3
7852  * \param [out] p the pos of plane
7853  */
7854 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7855 {
7856   std::size_t nbPoints=std::distance(begin,end);
7857   if(nbPoints<3)
7858     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7859   double vec[3]={0.,0.,0.};
7860   std::size_t j=0;
7861   bool refFound=false;
7862   for(;j<nbPoints-1 && !refFound;j++)
7863     {
7864       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7865       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7866       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7867       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7868       if(norm>eps)
7869         {
7870           refFound=true;
7871           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7872         }
7873     }
7874   for(std::size_t i=j;i<nbPoints-1;i++)
7875     {
7876       double curVec[3];
7877       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7878       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7879       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7880       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7881       if(norm<eps)
7882         continue;
7883       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7884       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];
7885       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7886       if(norm>eps)
7887         {
7888           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7889           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7890           return ;
7891         }
7892     }
7893   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7894 }
7895
7896 /*!
7897  * This method tries to obtain a well oriented polyhedron.
7898  * If the algorithm fails, an exception will be thrown.
7899  */
7900 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7901 {
7902   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7903   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7904   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7905   isPerm[0]=true;
7906   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7907   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7908   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7909   //
7910   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7911     {
7912       bgFace=begin;
7913       std::size_t smthChanged=0;
7914       for(std::size_t i=0;i<nbOfFaces;i++)
7915         {
7916           endFace=std::find(bgFace+1,end,-1);
7917           nbOfEdgesInFace=std::distance(bgFace,endFace);
7918           if(!isPerm[i])
7919             {
7920               bool b;
7921               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7922                 {
7923                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7924                   std::pair<int,int> p2(p1.second,p1.first);
7925                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7926                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7927                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7928                 }
7929               if(isPerm[i])
7930                 { 
7931                   if(!b)
7932                     std::reverse(bgFace+1,endFace);
7933                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7934                     {
7935                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7936                       std::pair<int,int> p2(p1.second,p1.first);
7937                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7938                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7939                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7940                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7941                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7942                       if(it!=edgesOK.end())
7943                         {
7944                           edgesOK.erase(it);
7945                           edgesFinished.push_back(p1);
7946                         }
7947                       else
7948                         edgesOK.push_back(p1);
7949                     }
7950                 }
7951             }
7952           bgFace=endFace+1;
7953         }
7954       if(smthChanged==0)
7955         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7956     }
7957   if(!edgesOK.empty())
7958     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7959   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7960     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7961       bgFace=begin;
7962       for(std::size_t i=0;i<nbOfFaces;i++)
7963         {
7964           endFace=std::find(bgFace+1,end,-1);
7965           std::reverse(bgFace+1,endFace);
7966           bgFace=endFace+1;
7967         }
7968     }
7969 }
7970
7971 /*!
7972  * This method makes the assumption spacedimension == meshdimension == 2.
7973  * This method works only for linear cells.
7974  * 
7975  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7976  */
7977 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7978 {
7979   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7980     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7981   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7983   int nbOfNodesExpected=m->getNumberOfNodes();
7984   if(m->getNumberOfCells()!=nbOfNodesExpected)
7985     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7986   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7987   const int *n2oPtr=n2o->getConstPointer();
7988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7989   m->getReverseNodalConnectivity(revNodal,revNodalI);
7990   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7991   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7992   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7993   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7994   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7995   if(nbOfNodesExpected<1)
7996     return ret.retn();
7997   int prevCell=0;
7998   int prevNode=nodalPtr[nodalIPtr[0]+1];
7999   *work++=n2oPtr[prevNode];
8000   for(int i=1;i<nbOfNodesExpected;i++)
8001     {
8002       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8003         {
8004           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8005           conn.erase(prevNode);
8006           if(conn.size()==1)
8007             {
8008               int curNode=*(conn.begin());
8009               *work++=n2oPtr[curNode];
8010               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8011               shar.erase(prevCell);
8012               if(shar.size()==1)
8013                 {
8014                   prevCell=*(shar.begin());
8015                   prevNode=curNode;
8016                 }
8017               else
8018                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8019             }
8020           else
8021             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8022         }
8023       else
8024         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8025     }
8026   return ret.retn();
8027 }
8028
8029 /*!
8030  * This method makes the assumption spacedimension == meshdimension == 3.
8031  * This method works only for linear cells.
8032  * 
8033  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8034  */
8035 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8036 {
8037   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8038     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8039   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8040   const int *conn=m->getNodalConnectivity()->getConstPointer();
8041   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8042   int nbOfCells=m->getNumberOfCells();
8043   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8044   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8045   if(nbOfCells<1)
8046     return ret.retn();
8047   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8048   for(int i=1;i<nbOfCells;i++)
8049     {
8050       *work++=-1;
8051       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8052     }
8053   return ret.retn();
8054 }
8055
8056 /*!
8057  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8058  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8059  */
8060 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8061 {
8062   double *w=zipFrmt;
8063   if(spaceDim==3)
8064     for(int i=0;i<nbOfNodesInCell;i++)
8065       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8066   else if(spaceDim==2)
8067     {
8068       for(int i=0;i<nbOfNodesInCell;i++)
8069         {
8070           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8071           *w++=0.;
8072         }
8073     }
8074   else
8075     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8076 }
8077
8078 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const throw(INTERP_KERNEL::Exception)
8079 {
8080   int nbOfCells=getNumberOfCells();
8081   if(nbOfCells<=0)
8082     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8083   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};
8084   ofs << "  <" << getVTKDataSetType() << ">\n";
8085   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8086   ofs << "      <PointData>\n" << pointData << std::endl;
8087   ofs << "      </PointData>\n";
8088   ofs << "      <CellData>\n" << cellData << std::endl;
8089   ofs << "      </CellData>\n";
8090   ofs << "      <Points>\n";
8091   if(getSpaceDimension()==3)
8092     _coords->writeVTK(ofs,8,"Points",byteData);
8093   else
8094     {
8095       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8096       coo->writeVTK(ofs,8,"Points",byteData);
8097     }
8098   ofs << "      </Points>\n";
8099   ofs << "      <Cells>\n";
8100   const int *cPtr=_nodal_connec->getConstPointer();
8101   const int *cIPtr=_nodal_connec_index->getConstPointer();
8102   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8106   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8107   int szFaceOffsets=0,szConn=0;
8108   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8109     {
8110       *w2=cPtr[cIPtr[i]];
8111       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8112         {
8113           *w1=-1;
8114           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8115           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8116         }
8117       else
8118         {
8119           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8120           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8121           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8122           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8123           w4=std::copy(c.begin(),c.end(),w4);
8124         }
8125     }
8126   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8127   types->writeVTK(ofs,8,"UInt8","types",byteData);
8128   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8129   if(szFaceOffsets!=0)
8130     {//presence of Polyhedra
8131       connectivity->reAlloc(szConn);
8132       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8133       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8134       w1=faces->getPointer();
8135       for(int i=0;i<nbOfCells;i++)
8136         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8137           {
8138             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8139             *w1++=nbFaces;
8140             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8141             for(int j=0;j<nbFaces;j++)
8142               {
8143                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8144                 *w1++=(int)std::distance(w6,w5);
8145                 w1=std::copy(w6,w5,w1);
8146                 w6=w5+1;
8147               }
8148           }
8149       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8150     }
8151   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8152   ofs << "      </Cells>\n";
8153   ofs << "    </Piece>\n";
8154   ofs << "  </" << getVTKDataSetType() << ">\n";
8155 }
8156
8157 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8158 {
8159   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8160   if(_mesh_dim==-2)
8161     { stream << " Not set !"; return ; }
8162   stream << " Mesh dimension : " << _mesh_dim << ".";
8163   if(_mesh_dim==-1)
8164     return ;
8165   if(!_coords)
8166     { stream << " No coordinates set !"; return ; }
8167   if(!_coords->isAllocated())
8168     { stream << " Coordinates set but not allocated !"; return ; }
8169   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8170   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8171   if(!_nodal_connec_index)
8172     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8173   if(!_nodal_connec_index->isAllocated())
8174     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8175   int lgth=_nodal_connec_index->getNumberOfTuples();
8176   int cpt=_nodal_connec_index->getNumberOfComponents();
8177   if(cpt!=1 || lgth<1)
8178     return ;
8179   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8180 }
8181
8182 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8183 {
8184   return std::string("UnstructuredGrid");
8185 }
8186
8187 /*!
8188  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8189  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8190  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8191  * meshes.
8192  *  \param [in] m1 - the first input mesh which is a partitioned object.
8193  *  \param [in] m2 - the second input mesh which is a partition tool.
8194  *  \param [in] eps - precision used to detect coincident mesh entities.
8195  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8196  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8197  *         this array using decrRef() as it is no more needed.
8198  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8199  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8200  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8201  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8202  *         it is no more needed.  
8203  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8204  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8205  *         is no more needed.  
8206  *  \throw If the coordinates array is not set in any of the meshes.
8207  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8208  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8209  */
8210 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8211 {
8212   m1->checkFullyDefined();
8213   m2->checkFullyDefined();
8214   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8215     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8216   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8217   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8218   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8219   std::vector<double> addCoo,addCoordsQuadratic;
8220   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8221   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8222   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8223                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8224   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8225   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8226   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8227   std::vector< std::vector<int> > intersectEdge2;
8228   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8229   subDiv2.clear(); dd5=0; dd6=0;
8230   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8231   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8232   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8233                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8234   //
8235   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8236   addCooDa->alloc((int)(addCoo.size())/2,2);
8237   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8238   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8239   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8240   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8241   std::vector<const DataArrayDouble *> coordss(4);
8242   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8243   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8244   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8245   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8246   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8247   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8249   ret->setConnectivity(conn,connI,true);
8250   ret->setCoords(coo);
8251   cellNb1=c1.retn(); cellNb2=c2.retn();
8252   return ret.retn();
8253 }
8254
8255 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8256                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8257                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8258                                                          const std::vector<double>& addCoords,
8259                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8260 {
8261   static const int SPACEDIM=2;
8262   const double *coo1=m1->getCoords()->getConstPointer();
8263   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8264   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8265   int offset1=m1->getNumberOfNodes();
8266   const double *coo2=m2->getCoords()->getConstPointer();
8267   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8268   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8269   int offset2=offset1+m2->getNumberOfNodes();
8270   int offset3=offset2+((int)addCoords.size())/2;
8271   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8272   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8273   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8274   int ncell1=m1->getNumberOfCells();
8275   crI.push_back(0);
8276   for(int i=0;i<ncell1;i++)
8277     {
8278       std::vector<int> candidates2;
8279       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8280       std::map<INTERP_KERNEL::Node *,int> mapp;
8281       std::map<int,INTERP_KERNEL::Node *> mappRev;
8282       INTERP_KERNEL::QuadraticPolygon pol1;
8283       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8284       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8285       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8286       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8287                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8288       //
8289       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
8290       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8291       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8292       for(it1.first();!it1.finished();it1.next())
8293         edges1.insert(it1.current()->getPtr());
8294       //
8295       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8296       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8297       int ii=0;
8298       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8299         {
8300           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8301           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8302           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8303           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8304                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8305         }
8306       ii=0;
8307       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8308         {
8309           pol1.initLocationsWithOther(pol2s[ii]);
8310           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8311           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8312           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8313         }
8314       if(!edges1.empty())
8315         {
8316           try
8317             {
8318               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8319             }
8320           catch(INTERP_KERNEL::Exception& e)
8321             {
8322               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();
8323               throw INTERP_KERNEL::Exception(oss.str().c_str());
8324             }
8325         }
8326       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8327         (*it).second->decrRef();
8328     }
8329 }
8330
8331 /*!
8332  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8333  * 
8334  */
8335 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8336                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8337                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8338                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8339                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8340 {
8341   static const int SPACEDIM=2;
8342   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8343   desc2=DataArrayInt::New();
8344   descIndx2=DataArrayInt::New();
8345   revDesc2=DataArrayInt::New();
8346   revDescIndx2=DataArrayInt::New();
8347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8349   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8350   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8351   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8352   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8353   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8354   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8355   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8356   int ncell1=m1Desc->getNumberOfCells();
8357   int ncell2=m2Desc->getNumberOfCells();
8358   intersectEdge1.resize(ncell1);
8359   colinear2.resize(ncell2);
8360   subDiv2.resize(ncell2);
8361   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8362   std::vector<int> candidates1(1);
8363   int offset1=m1->getNumberOfNodes();
8364   int offset2=offset1+m2->getNumberOfNodes();
8365   for(int i=0;i<ncell1;i++)
8366     {
8367       std::vector<int> candidates2;
8368       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8369       if(!candidates2.empty())
8370         {
8371           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8372           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8373           candidates1[0]=i;
8374           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8375           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8376           delete pol2;
8377           delete pol1;
8378         }
8379       else
8380         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8381     }
8382   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8383   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8384 }
8385
8386 /*!
8387  * This method performs the 2nd step of Partition of 2D mesh.
8388  * This method has 4 inputs :
8389  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8390  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8391  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8392  * 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'
8393  * \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'
8394  * \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.
8395  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8396  */
8397 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)
8398 {
8399   int offset1=m1->getNumberOfNodes();
8400   int ncell=m2->getNumberOfCells();
8401   const int *c=m2->getNodalConnectivity()->getConstPointer();
8402   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8403   const double *coo=m2->getCoords()->getConstPointer();
8404   const double *cooBis=m1->getCoords()->getConstPointer();
8405   int offset2=offset1+m2->getNumberOfNodes();
8406   intersectEdge.resize(ncell);
8407   for(int i=0;i<ncell;i++,cI++)
8408     {
8409       const std::vector<int>& divs=subDiv[i];
8410       int nnode=cI[1]-cI[0]-1;
8411       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8412       std::map<INTERP_KERNEL::Node *, int> mapp22;
8413       for(int j=0;j<nnode;j++)
8414         {
8415           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8416           int nnid=c[(*cI)+j+1];
8417           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8418           mapp22[nn]=nnid+offset1;
8419         }
8420       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8421       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8422         ((*it).second.first)->decrRef();
8423       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8424       std::map<INTERP_KERNEL::Node *,int> mapp3;
8425       for(std::size_t j=0;j<divs.size();j++)
8426         {
8427           int id=divs[j];
8428           INTERP_KERNEL::Node *tmp=0;
8429           if(id<offset1)
8430             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8431           else if(id<offset2)
8432             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8433           else
8434             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8435           addNodes[j]=tmp;
8436           mapp3[tmp]=id;
8437         }
8438       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8439       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8440         (*it)->decrRef();
8441       e->decrRef();
8442     }
8443 }
8444
8445 /*!
8446  * 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).
8447  * 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
8448  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8449  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8450  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8451  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8452  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8453  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8454  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8455  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8456  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8457  * \param [out] cut3DSuf input/output param.
8458  */
8459 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8460                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8461                                                    const int *desc, const int *descIndx, 
8462                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8463 {
8464   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8465   int nbOf3DSurfCell=(int)cut3DSurf.size();
8466   for(int i=0;i<nbOf3DSurfCell;i++)
8467     {
8468       std::vector<int> res;
8469       int offset=descIndx[i];
8470       int nbOfSeg=descIndx[i+1]-offset;
8471       for(int j=0;j<nbOfSeg;j++)
8472         {
8473           int edgeId=desc[offset+j];
8474           int status=cut3DCurve[edgeId];
8475           if(status!=-2)
8476             {
8477               if(status>-1)
8478                 res.push_back(status);
8479               else
8480                 {
8481                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8482                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8483                 }
8484             }
8485         }
8486       switch(res.size())
8487         {
8488         case 2:
8489           {
8490             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8491             break;
8492           }
8493         case 1:
8494         case 0:
8495           {
8496             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8497             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8498             if(res.size()==2)
8499               {
8500                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8501               }
8502             else
8503               {
8504                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8505               }
8506             break;
8507           }
8508         default:
8509           {// case when plane is on a multi colinear edge of a polyhedron
8510             if((int)res.size()==2*nbOfSeg)
8511               {
8512                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8513               }
8514             else
8515               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8516           }
8517         }
8518     }
8519 }
8520
8521 /*!
8522  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8523  * 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).
8524  * 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
8525  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8526  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8527  * \param desc is the descending connectivity 3D->3DSurf
8528  * \param descIndx is the descending connectivity index 3D->3DSurf
8529  */
8530 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8531                                                   const int *desc, const int *descIndx,
8532                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8533 {
8534   checkFullyDefined();
8535   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8536     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8537   const int *nodal3D=_nodal_connec->getConstPointer();
8538   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8539   int nbOfCells=getNumberOfCells();
8540   for(int i=0;i<nbOfCells;i++)
8541     {
8542       std::map<int, std::set<int> > m;
8543       int offset=descIndx[i];
8544       int nbOfFaces=descIndx[i+1]-offset;
8545       int start=-1;
8546       int end=-1;
8547       for(int j=0;j<nbOfFaces;j++)
8548         {
8549           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8550           if(p.first!=-1 && p.second!=-1)
8551             {
8552               if(p.first!=-2)
8553                 {
8554                   start=p.first; end=p.second;
8555                   m[p.first].insert(p.second);
8556                   m[p.second].insert(p.first);
8557                 }
8558               else
8559                 {
8560                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8561                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8562                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8563                   INTERP_KERNEL::NormalizedCellType cmsId;
8564                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8565                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8566                   for(unsigned k=0;k<nbOfNodesSon;k++)
8567                     {
8568                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8569                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8570                     }
8571                 }
8572             }
8573         }
8574       if(m.empty())
8575         continue;
8576       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8577       int prev=end;
8578       while(end!=start)
8579         {
8580           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8581           const std::set<int>& s=(*it).second;
8582           std::set<int> s2; s2.insert(prev);
8583           std::set<int> s3;
8584           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8585           if(s3.size()==1)
8586             {
8587               int val=*s3.begin();
8588               conn.push_back(start);
8589               prev=start;
8590               start=val;
8591             }
8592           else
8593             start=end;
8594         }
8595       conn.push_back(end);
8596       if(conn.size()>3)
8597         {
8598           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8599           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8600           cellIds->pushBackSilent(i);
8601         }
8602     }
8603 }
8604
8605 /*!
8606  * 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
8607  * 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
8608  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8609  * 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
8610  * 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.
8611  * 
8612  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8613  */
8614 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8615 {
8616   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8617   if(sz>=4)
8618     {
8619       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8620       if(cm.getDimension()==2)
8621         {
8622           const int *node=nodalConnBg+1;
8623           int startNode=*node++;
8624           double refX=coords[2*startNode];
8625           for(;node!=nodalConnEnd;node++)
8626             {
8627               if(coords[2*(*node)]<refX)
8628                 {
8629                   startNode=*node;
8630                   refX=coords[2*startNode];
8631                 }
8632             }
8633           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8634           refX=1e300;
8635           double tmp1;
8636           double tmp2[2];
8637           double angle0=-M_PI/2;
8638           //
8639           int nextNode=-1;
8640           int prevNode=-1;
8641           double resRef;
8642           double angleNext=0.;
8643           while(nextNode!=startNode)
8644             {
8645               nextNode=-1;
8646               resRef=1e300;
8647               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8648                 {
8649                   if(*node!=tmpOut.back() && *node!=prevNode)
8650                     {
8651                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8652                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8653                       double res;
8654                       if(angleM<=angle0)
8655                         res=angle0-angleM;
8656                       else
8657                         res=angle0-angleM+2.*M_PI;
8658                       if(res<resRef)
8659                         {
8660                           nextNode=*node;
8661                           resRef=res;
8662                           angleNext=angleM;
8663                         }
8664                     }
8665                 }
8666               if(nextNode!=startNode)
8667                 {
8668                   angle0=angleNext-M_PI;
8669                   if(angle0<-M_PI)
8670                     angle0+=2*M_PI;
8671                   prevNode=tmpOut.back();
8672                   tmpOut.push_back(nextNode);
8673                 }
8674             }
8675           std::vector<int> tmp3(2*(sz-1));
8676           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8677           std::copy(nodalConnBg+1,nodalConnEnd,it);
8678           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8679             {
8680               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8681               return false;
8682             }
8683           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8684             {
8685               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8686               return false;
8687             }
8688           else
8689             {
8690               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8691               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8692               return true;
8693             }
8694         }
8695       else
8696         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8697     }
8698   else
8699     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8700 }
8701
8702 /*!
8703  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8704  * 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.
8705  * 
8706  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8707  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8708  * \param [in,out] arr array in which the remove operation will be done.
8709  * \param [in,out] arrIndx array in the remove operation will modify
8710  * \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])
8711  * \return true if \b arr and \b arrIndx have been modified, false if not.
8712  */
8713 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8714 {
8715   if(!arrIndx || !arr)
8716     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8717   if(offsetForRemoval<0)
8718     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8719   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8720   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8721   int *arrIPtr=arrIndx->getPointer();
8722   *arrIPtr++=0;
8723   int previousArrI=0;
8724   const int *arrPtr=arr->getConstPointer();
8725   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8726   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8727     {
8728       if(*arrIPtr-previousArrI>offsetForRemoval)
8729         {
8730           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8731             {
8732               if(s.find(*work)==s.end())
8733                 arrOut.push_back(*work);
8734             }
8735         }
8736       previousArrI=*arrIPtr;
8737       *arrIPtr=(int)arrOut.size();
8738     }
8739   if(arr->getNumberOfTuples()==(int)arrOut.size())
8740     return false;
8741   arr->alloc((int)arrOut.size(),1);
8742   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8743   return true;
8744 }
8745
8746 /*!
8747  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8748  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8749  * The selection of extraction is done standardly in new2old format.
8750  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8751  *
8752  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8753  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8754  * \param [in] arrIn arr origin array from which the extraction will be done.
8755  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8756  * \param [out] arrOut the resulting array
8757  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8758  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8759  */
8760 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8761                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8762 {
8763   if(!arrIn || !arrIndxIn)
8764     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8765   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8766   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8767     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8768   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8769   const int *arrInPtr=arrIn->getConstPointer();
8770   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8771   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8772   if(nbOfGrps<0)
8773     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8774   int maxSizeOfArr=arrIn->getNumberOfTuples();
8775   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8776   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8777   arrIo->alloc((int)(sz+1),1);
8778   const int *idsIt=idsOfSelectBg;
8779   int *work=arrIo->getPointer();
8780   *work++=0;
8781   int lgth=0;
8782   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8783     {
8784       if(*idsIt>=0 && *idsIt<nbOfGrps)
8785         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8786       else
8787         {
8788           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8789           throw INTERP_KERNEL::Exception(oss.str().c_str());
8790         }
8791       if(lgth>=work[-1])
8792         *work=lgth;
8793       else
8794         {
8795           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8796           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8797           throw INTERP_KERNEL::Exception(oss.str().c_str());
8798         }
8799     }
8800   arro->alloc(lgth,1);
8801   work=arro->getPointer();
8802   idsIt=idsOfSelectBg;
8803   for(std::size_t i=0;i<sz;i++,idsIt++)
8804     {
8805       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8806         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8807       else
8808         {
8809           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8810           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8811           throw INTERP_KERNEL::Exception(oss.str().c_str());
8812         }
8813     }
8814   arrOut=arro.retn();
8815   arrIndexOut=arrIo.retn();
8816 }
8817
8818 /*!
8819  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8820  * 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 ).
8821  * The selection of extraction is done standardly in new2old format.
8822  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8823  *
8824  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8825  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8826  * \param [in] arrIn arr origin array from which the extraction will be done.
8827  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8828  * \param [out] arrOut the resulting array
8829  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8830  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8831  */
8832 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8833                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8834 {
8835   if(!arrIn || !arrIndxIn)
8836     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8837   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8838   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8840   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8841   const int *arrInPtr=arrIn->getConstPointer();
8842   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8843   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8844   if(nbOfGrps<0)
8845     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8846   int maxSizeOfArr=arrIn->getNumberOfTuples();
8847   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8849   arrIo->alloc((int)(sz+1),1);
8850   int idsIt=idsOfSelectStart;
8851   int *work=arrIo->getPointer();
8852   *work++=0;
8853   int lgth=0;
8854   for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8855     {
8856       if(idsIt>=0 && idsIt<nbOfGrps)
8857         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8858       else
8859         {
8860           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8861           throw INTERP_KERNEL::Exception(oss.str().c_str());
8862         }
8863       if(lgth>=work[-1])
8864         *work=lgth;
8865       else
8866         {
8867           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8868           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8869           throw INTERP_KERNEL::Exception(oss.str().c_str());
8870         }
8871     }
8872   arro->alloc(lgth,1);
8873   work=arro->getPointer();
8874   idsIt=idsOfSelectStart;
8875   for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8876     {
8877       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8878         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8879       else
8880         {
8881           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8882           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8883           throw INTERP_KERNEL::Exception(oss.str().c_str());
8884         }
8885     }
8886   arrOut=arro.retn();
8887   arrIndexOut=arrIo.retn();
8888 }
8889
8890 /*!
8891  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8892  * This method 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
8893  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8894  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8895  *
8896  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8897  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8898  * \param [in] arrIn arr origin array from which the extraction will be done.
8899  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8900  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8901  * \param [in] srcArrIndex index array of \b srcArr
8902  * \param [out] arrOut the resulting array
8903  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8904  * 
8905  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8906  */
8907 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8908                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8909                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8910 {
8911   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8912     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8913   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8915   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8916   std::vector<bool> v(nbOfTuples,true);
8917   int offset=0;
8918   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8919   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8920   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8921     {
8922       if(*it>=0 && *it<nbOfTuples)
8923         {
8924           v[*it]=false;
8925           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8926         }
8927       else
8928         {
8929           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8930           throw INTERP_KERNEL::Exception(oss.str().c_str());
8931         }
8932     }
8933   srcArrIndexPtr=srcArrIndex->getConstPointer();
8934   arrIo->alloc(nbOfTuples+1,1);
8935   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8936   const int *arrInPtr=arrIn->getConstPointer();
8937   const int *srcArrPtr=srcArr->getConstPointer();
8938   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8939   int *arroPtr=arro->getPointer();
8940   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8941     {
8942       if(v[ii])
8943         {
8944           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8945           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8946         }
8947       else
8948         {
8949           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8950           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8951           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8952         }
8953     }
8954   arrOut=arro.retn();
8955   arrIndexOut=arrIo.retn();
8956 }
8957
8958 /*!
8959  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8960  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8961  *
8962  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8963  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8964  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8965  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8966  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8967  * \param [in] srcArrIndex index array of \b srcArr
8968  * 
8969  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8970  */
8971 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8972                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8973 {
8974   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8975     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8976   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8977   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8978   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8979   int *arrInOutPtr=arrInOut->getPointer();
8980   const int *srcArrPtr=srcArr->getConstPointer();
8981   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8982     {
8983       if(*it>=0 && *it<nbOfTuples)
8984         {
8985           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8986             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8987           else
8988             {
8989               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] !";
8990               throw INTERP_KERNEL::Exception(oss.str().c_str());
8991             }
8992         }
8993       else
8994         {
8995           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8996           throw INTERP_KERNEL::Exception(oss.str().c_str());
8997         }
8998     }
8999 }
9000
9001 /*!
9002  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9003  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9004  * 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]].
9005  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9006  * A negative value in \b arrIn means that it is ignored.
9007  * 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.
9008  * 
9009  * \param [in] arrIn arr origin array from which the extraction will be done.
9010  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9011  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9012  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9013  */
9014 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9015 {
9016   int seed=0,nbOfDepthPeelingPerformed=0;
9017   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9018 }
9019
9020 /*!
9021  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9022  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9023  * 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]].
9024  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9025  * A negative value in \b arrIn means that it is ignored.
9026  * 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.
9027  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9028  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9029  * \param [in] arrIn arr origin array from which the extraction will be done.
9030  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9031  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9032  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9033  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9034  * \sa MEDCouplingUMesh::partitionBySpreadZone
9035  */
9036 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9037 {
9038   nbOfDepthPeelingPerformed=0;
9039   if(!arrIndxIn)
9040     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9041   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9042   if(nbOfTuples<=0)
9043     {
9044       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9045       return ret;
9046     }
9047   //
9048   std::vector<bool> fetched(nbOfTuples,false);
9049   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9050 }
9051
9052 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)
9053 {
9054   nbOfDepthPeelingPerformed=0;
9055   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9056     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9057   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9058   std::vector<bool> fetched2(nbOfTuples,false);
9059   int i=0;
9060   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9061     {
9062       if(*seedElt>=0 && *seedElt<nbOfTuples)
9063         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9064       else
9065         { 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()); }
9066     }
9067   const int *arrInPtr=arrIn->getConstPointer();
9068   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9069   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9070   std::vector<int> idsToFetch1(seedBg,seedEnd);
9071   std::vector<int> idsToFetch2;
9072   std::vector<int> *idsToFetch=&idsToFetch1;
9073   std::vector<int> *idsToFetchOther=&idsToFetch2;
9074   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9075     {
9076       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9077         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9078           if(!fetched[*it2])
9079             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9080       std::swap(idsToFetch,idsToFetchOther);
9081       idsToFetchOther->clear();
9082       nbOfDepthPeelingPerformed++;
9083     }
9084   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9085   i=0;
9086   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9087   int *retPtr=ret->getPointer();
9088   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9089     if(*it)
9090       *retPtr++=i;
9091   return ret.retn();
9092 }
9093
9094 /*!
9095  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9096  * 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
9097  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9098  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9099  *
9100  * \param [in] start begin of set of ids of the input extraction (included)
9101  * \param [in] end end of set of ids of the input extraction (excluded)
9102  * \param [in] step step of the set of ids in range mode.
9103  * \param [in] arrIn arr origin array from which the extraction will be done.
9104  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9105  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9106  * \param [in] srcArrIndex index array of \b srcArr
9107  * \param [out] arrOut the resulting array
9108  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9109  * 
9110  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9111  */
9112 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9113                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9114                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9115 {
9116   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9117     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9118   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9119   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9120   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9121   int offset=0;
9122   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9123   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9124   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9125   int it=start;
9126   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9127     {
9128       if(it>=0 && it<nbOfTuples)
9129         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9130       else
9131         {
9132           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9133           throw INTERP_KERNEL::Exception(oss.str().c_str());
9134         }
9135     }
9136   srcArrIndexPtr=srcArrIndex->getConstPointer();
9137   arrIo->alloc(nbOfTuples+1,1);
9138   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9139   const int *arrInPtr=arrIn->getConstPointer();
9140   const int *srcArrPtr=srcArr->getConstPointer();
9141   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9142   int *arroPtr=arro->getPointer();
9143   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9144     {
9145       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9146       if(pos<0)
9147         {
9148           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9149           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9150         }
9151       else
9152         {
9153           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9154           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9155         }
9156     }
9157   arrOut=arro.retn();
9158   arrIndexOut=arrIo.retn();
9159 }
9160
9161 /*!
9162  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9163  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9164  *
9165  * \param [in] start begin of set of ids of the input extraction (included)
9166  * \param [in] end end of set of ids of the input extraction (excluded)
9167  * \param [in] step step of the set of ids in range mode.
9168  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9169  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9170  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9171  * \param [in] srcArrIndex index array of \b srcArr
9172  * 
9173  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9174  */
9175 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9176                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9177 {
9178   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9179     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9180   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9181   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9182   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9183   int *arrInOutPtr=arrInOut->getPointer();
9184   const int *srcArrPtr=srcArr->getConstPointer();
9185   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9186   int it=start;
9187   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9188     {
9189       if(it>=0 && it<nbOfTuples)
9190         {
9191           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9192             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9193           else
9194             {
9195               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9196               throw INTERP_KERNEL::Exception(oss.str().c_str());
9197             }
9198         }
9199       else
9200         {
9201           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9202           throw INTERP_KERNEL::Exception(oss.str().c_str());
9203         }
9204     }
9205 }
9206
9207 /*!
9208  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9209  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9210  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9211  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9212  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9213  * 
9214  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9215  */
9216 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9217 {
9218   checkFullyDefined();
9219   int mdim=getMeshDimension();
9220   int spaceDim=getSpaceDimension();
9221   if(mdim!=spaceDim)
9222     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9223   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9224   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9225   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9226   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9227   ret->setCoords(getCoords());
9228   ret->allocateCells((int)partition.size());
9229   //
9230   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9231     {
9232       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9233       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9234       switch(mdim)
9235         {
9236         case 2:
9237           cell=tmp->buildUnionOf2DMesh();
9238           break;
9239         case 3:
9240           cell=tmp->buildUnionOf3DMesh();
9241           break;
9242         default:
9243           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9244         }
9245       
9246       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9247     }
9248   //
9249   ret->finishInsertingCells();
9250   return ret.retn();
9251 }
9252
9253 /*!
9254  * This method partitions \b this into contiguous zone.
9255  * This method only needs a well defined connectivity. Coordinates are not considered here.
9256  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9257  */
9258 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9259 {
9260   int nbOfCellsCur=getNumberOfCells();
9261   std::vector<DataArrayInt *> ret;
9262   if(nbOfCellsCur<=0)
9263     return ret;
9264   DataArrayInt *neigh=0,*neighI=0;
9265   computeNeighborsOfCells(neigh,neighI);
9266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9267   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9268   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9269   int seed=0;
9270   while(seed<nbOfCellsCur)
9271     {
9272       int nbOfPeelPerformed=0;
9273       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9274       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9275     }
9276   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9277     ret.push_back((*it).retn());
9278   return ret;
9279 }
9280
9281 /*!
9282  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9283  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9284  *
9285  * \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.
9286  * \return a newly allocated DataArrayInt to be managed by the caller.
9287  * \throw In case of \a code has not the right format (typically of size 3*n)
9288  */
9289 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9290 {
9291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9292   std::size_t nb=code.size()/3;
9293   if(code.size()%3!=0)
9294     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9295   ret->alloc((int)nb,2);
9296   int *retPtr=ret->getPointer();
9297   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9298     {
9299       retPtr[0]=code[3*i+2];
9300       retPtr[1]=code[3*i+2]+code[3*i+1];
9301     }
9302   return ret.retn();
9303 }
9304
9305 /*!
9306  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9307  * All cells in \a this are expected to be linear 3D cells.
9308  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9309  * It leads to an increase to number of cells.
9310  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9311  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
9312  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9313  *
9314  * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells.
9315  *                      For all other cells, the splitting policy will be ignored.
9316  * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added. 
9317  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9318  *          an id of old cell producing it. The caller is to delete this array using
9319  *         decrRef() as it is no more needed.
9320  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9321  * 
9322  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9323  * \throw If \a this is not fully constituted with linear 3D cells.
9324  * \sa MEDCouplingUMesh::simplexize
9325  */
9326 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const throw(INTERP_KERNEL::Exception)
9327 {
9328   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9329   checkConnectivityFullyDefined();
9330   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9331     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9332   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9333   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
9334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9335   int *retPt(ret->getPointer());
9336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9337   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9338   const int *oldc(_nodal_connec->begin());
9339   const int *oldci(_nodal_connec_index->begin());
9340   const double *coords(_coords->begin());
9341   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9342     {
9343       std::vector<int> a; std::vector<double> b;
9344       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9345       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9346       const int *aa(&a[0]);
9347       if(!b.empty())
9348         {
9349           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9350             if(*it<0)
9351               *it=(-(*(it))-1+nbNodes);
9352           addPts->insertAtTheEnd(b.begin(),b.end());
9353           nbNodes+=(int)b.size()/3;
9354         }
9355       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9356         newConn->insertAtTheEnd(aa,aa+4);
9357     }
9358   if(!addPts->empty())
9359     {
9360       addPts->rearrange(3);
9361       nbOfAdditionalPoints=addPts->getNumberOfTuples();
9362       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9363       ret0->setCoords(addPts);
9364     }
9365   else
9366     {
9367       nbOfAdditionalPoints=0;
9368       ret0->setCoords(getCoords());
9369     }
9370   ret0->setNodalConnectivity(newConn);
9371   //
9372   ret->computeOffsets2();
9373   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9374   return ret0.retn();
9375 }
9376
9377 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9378                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9379 {
9380   if(mesh)
9381     {
9382       mesh->incrRef();
9383       _nb_cell=mesh->getNumberOfCells();
9384     }
9385 }
9386
9387 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9388 {
9389   if(_mesh)
9390     _mesh->decrRef();
9391   if(_own_cell)
9392     delete _cell;
9393 }
9394
9395 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9396                                                                                                                                _own_cell(false),_cell_id(bg-1),
9397                                                                                                                                _nb_cell(end)
9398 {
9399   if(mesh)
9400     mesh->incrRef();
9401 }
9402
9403 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9404 {
9405   _cell_id++;
9406   if(_cell_id<_nb_cell)
9407     {
9408       _cell->next();
9409       return _cell;
9410     }
9411   else
9412     return 0;
9413 }
9414
9415 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9416 {
9417   if(_mesh)
9418     _mesh->incrRef();
9419 }
9420
9421 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9422 {
9423   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9424 }
9425
9426 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9427 {
9428   if(_mesh)
9429     _mesh->decrRef();
9430 }
9431
9432 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9433                                                                                                                                                                   _itc(itc),
9434                                                                                                                                                                   _bg(bg),_end(end)
9435 {
9436   if(_mesh)
9437     _mesh->incrRef();
9438 }
9439
9440 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9441 {
9442   if(_mesh)
9443     _mesh->decrRef();
9444 }
9445
9446 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9447 {
9448   return _type;
9449 }
9450
9451 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9452 {
9453   return _end-_bg;
9454 }
9455
9456 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9457 {
9458   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9459 }
9460
9461 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9462 {
9463   if(mesh)
9464     {
9465       mesh->incrRef();
9466       _nb_cell=mesh->getNumberOfCells();
9467     }
9468 }
9469
9470 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9471 {
9472   if(_mesh)
9473     _mesh->decrRef();
9474   delete _cell;
9475 }
9476
9477 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9478 {
9479   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9480   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9481   if(_cell_id<_nb_cell)
9482     {
9483       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9484       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9485       int startId=_cell_id;
9486       _cell_id+=nbOfElems;
9487       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9488     }
9489   else
9490     return 0;
9491 }
9492
9493 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9494 {
9495   if(mesh)
9496     {
9497       _conn=mesh->getNodalConnectivity()->getPointer();
9498       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9499     }
9500 }
9501
9502 void MEDCouplingUMeshCell::next()
9503 {
9504   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9505     {
9506       _conn+=_conn_lgth;
9507       _conn_indx++;
9508     }
9509   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9510 }
9511
9512 std::string MEDCouplingUMeshCell::repr() const
9513 {
9514   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9515     {
9516       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9517       oss << " : ";
9518       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9519       return oss.str();
9520     }
9521   else
9522     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9523 }
9524
9525 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9526 {
9527   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9528     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9529   else
9530     return INTERP_KERNEL::NORM_ERROR;
9531 }
9532
9533 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9534 {
9535   lgth=_conn_lgth;
9536   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9537     return _conn;
9538   else
9539     return 0;
9540 }