Salome HOME
Management of QPOLYGON in MEDCouplingUMesh::orientCorrectly2DCells method.
[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
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)
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<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildren() const
125 {
126   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
127   if(_nodal_connec)
128     ret.push_back(_nodal_connec);
129   if(_nodal_connec_index)
130     ret.push_back(_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
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
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
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)
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()
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
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
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
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
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
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
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
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
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()
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)
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
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
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
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
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
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
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()
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
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
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
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
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)
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)
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
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
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
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
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)
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)
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)
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)
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
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
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
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
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
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
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
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
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
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
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
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
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)
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)
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()
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)
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
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
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
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()
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)
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
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
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
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
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
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
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)
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)
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 tessellation : 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)
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
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()
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()
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()
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()
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)
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()
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
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)
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               if(!isQuadratic)
5700                 {
5701                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5702                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5703                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5704                 }
5705               else
5706                 {
5707                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5708                   std::vector<int> tmp0(sz-1),tmp1(sz);
5709                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5710                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5711                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5712                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5713                 }
5714             }
5715         }
5716     }
5717   if(isModified)
5718     _nodal_connec->declareAsNew();
5719   updateTime();
5720 }
5721
5722 /*!
5723  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5724  * oriented facets. The normal vector of the facet should point out of the cell.
5725  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5726  *         is not cleared before filling in.
5727  *  \throw If \a this->getMeshDimension() != 3.
5728  *  \throw If \a this->getSpaceDimension() != 3.
5729  *  \throw If the coordinates array is not set.
5730  *  \throw If the nodal connectivity of cells is not defined.
5731  *
5732  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5733  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5734  */
5735 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5736 {
5737   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5738     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5739   int nbOfCells=getNumberOfCells();
5740   const int *conn=_nodal_connec->getConstPointer();
5741   const int *connI=_nodal_connec_index->getConstPointer();
5742   const double *coordsPtr=_coords->getConstPointer();
5743   for(int i=0;i<nbOfCells;i++)
5744     {
5745       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5746       if(type==INTERP_KERNEL::NORM_POLYHED)
5747         {
5748           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5749             cells.push_back(i);
5750         }
5751     }
5752 }
5753
5754 /*!
5755  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5756  * out of the cell. 
5757  *  \throw If \a this->getMeshDimension() != 3.
5758  *  \throw If \a this->getSpaceDimension() != 3.
5759  *  \throw If the coordinates array is not set.
5760  *  \throw If the nodal connectivity of cells is not defined.
5761  *  \throw If the reparation fails.
5762  *
5763  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5764  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5765  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5766  */
5767 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5768 {
5769   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5770     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5771   int nbOfCells=getNumberOfCells();
5772   int *conn=_nodal_connec->getPointer();
5773   const int *connI=_nodal_connec_index->getConstPointer();
5774   const double *coordsPtr=_coords->getConstPointer();
5775   for(int i=0;i<nbOfCells;i++)
5776     {
5777       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5778       if(type==INTERP_KERNEL::NORM_POLYHED)
5779         {
5780           try
5781             {
5782               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5783                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5784             }
5785           catch(INTERP_KERNEL::Exception& e)
5786             {
5787               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5788               throw INTERP_KERNEL::Exception(oss.str().c_str());
5789             }
5790         }
5791     }
5792   updateTime();
5793 }
5794
5795 /*!
5796  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5797  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5798  * according to which the first facet of the cell should be oriented to have the normal vector
5799  * pointing out of cell.
5800  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5801  *         cells. The caller is to delete this array using decrRef() as it is no more
5802  *         needed. 
5803  *  \throw If \a this->getMeshDimension() != 3.
5804  *  \throw If \a this->getSpaceDimension() != 3.
5805  *  \throw If the coordinates array is not set.
5806  *  \throw If the nodal connectivity of cells is not defined.
5807  *
5808  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5809  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5810  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5811  */
5812 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5813 {
5814   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5815   if(getMeshDimension()!=3)
5816     throw INTERP_KERNEL::Exception(msg);
5817   int spaceDim=getSpaceDimension();
5818   if(spaceDim!=3)
5819     throw INTERP_KERNEL::Exception(msg);
5820   //
5821   int nbOfCells=getNumberOfCells();
5822   int *conn=_nodal_connec->getPointer();
5823   const int *connI=_nodal_connec_index->getConstPointer();
5824   const double *coo=getCoords()->getConstPointer();
5825   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5826   for(int i=0;i<nbOfCells;i++)
5827     {
5828       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5829       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5830         {
5831           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5832             {
5833               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5834               cells->pushBackSilent(i);
5835             }
5836         }
5837     }
5838   return cells.retn();
5839 }
5840
5841 /*!
5842  * This method is a faster method to correct orientation of all 3D cells in \a this.
5843  * 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.
5844  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5845  * 
5846  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5847  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5848  */
5849 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5850 {
5851   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5852     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5853   int nbOfCells=getNumberOfCells();
5854   int *conn=_nodal_connec->getPointer();
5855   const int *connI=_nodal_connec_index->getConstPointer();
5856   const double *coordsPtr=_coords->getConstPointer();
5857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5858   for(int i=0;i<nbOfCells;i++)
5859     {
5860       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5861       switch(type)
5862         {
5863         case INTERP_KERNEL::NORM_TETRA4:
5864           {
5865             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5866               {
5867                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5868                 ret->pushBackSilent(i);
5869               }
5870             break;
5871           }
5872         case INTERP_KERNEL::NORM_PYRA5:
5873           {
5874             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5875               {
5876                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5877                 ret->pushBackSilent(i);
5878               }
5879             break;
5880           }
5881         case INTERP_KERNEL::NORM_PENTA6:
5882         case INTERP_KERNEL::NORM_HEXA8:
5883         case INTERP_KERNEL::NORM_HEXGP12:
5884           {
5885             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5886               {
5887                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5888                 ret->pushBackSilent(i);
5889               }
5890             break;
5891           }
5892         case INTERP_KERNEL::NORM_POLYHED:
5893           {
5894             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5895               {
5896                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5897                 ret->pushBackSilent(i);
5898               }
5899             break;
5900           }
5901         default:
5902           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 !");
5903         }
5904     }
5905   updateTime();
5906   return ret.retn();
5907 }
5908
5909 /*!
5910  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5911  * If it is not the case an exception will be thrown.
5912  * This method is fast because the first cell of \a this is used to compute the plane.
5913  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5914  * \param pos output of size at least 3 used to store a point owned of searched plane.
5915  */
5916 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5917 {
5918   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5919     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5920   const int *conn=_nodal_connec->getConstPointer();
5921   const int *connI=_nodal_connec_index->getConstPointer();
5922   const double *coordsPtr=_coords->getConstPointer();
5923   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5924   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5925 }
5926
5927 /*!
5928  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5929  * cells. Currently cells of the following types are treated:
5930  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5931  * For a cell of other type an exception is thrown.
5932  * Space dimension of a 2D mesh can be either 2 or 3.
5933  * The Edge Ratio of a cell \f$t\f$ is: 
5934  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5935  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5936  *  the smallest edge lengths of \f$t\f$.
5937  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5938  *          cells and one time, lying on \a this mesh. The caller is to delete this
5939  *          field using decrRef() as it is no more needed. 
5940  *  \throw If the coordinates array is not set.
5941  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5942  *  \throw If the connectivity data array has more than one component.
5943  *  \throw If the connectivity data array has a named component.
5944  *  \throw If the connectivity index data array has more than one component.
5945  *  \throw If the connectivity index data array has a named component.
5946  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5947  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5948  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5949  */
5950 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
5951 {
5952   checkCoherency();
5953   int spaceDim=getSpaceDimension();
5954   int meshDim=getMeshDimension();
5955   if(spaceDim!=2 && spaceDim!=3)
5956     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5957   if(meshDim!=2 && meshDim!=3)
5958     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5959   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5960   ret->setMesh(this);
5961   int nbOfCells=getNumberOfCells();
5962   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5963   arr->alloc(nbOfCells,1);
5964   double *pt=arr->getPointer();
5965   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5966   const int *conn=_nodal_connec->getConstPointer();
5967   const int *connI=_nodal_connec_index->getConstPointer();
5968   const double *coo=_coords->getConstPointer();
5969   double tmp[12];
5970   for(int i=0;i<nbOfCells;i++,pt++)
5971     {
5972       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5973       switch(t)
5974         {
5975           case INTERP_KERNEL::NORM_TRI3:
5976             {
5977               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5978               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5979               break;
5980             }
5981           case INTERP_KERNEL::NORM_QUAD4:
5982             {
5983               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5984               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5985               break;
5986             }
5987           case INTERP_KERNEL::NORM_TETRA4:
5988             {
5989               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5990               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5991               break;
5992             }
5993         default:
5994           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5995         }
5996       conn+=connI[i+1]-connI[i];
5997     }
5998   ret->setName("EdgeRatio");
5999   ret->synchronizeTimeWithSupport();
6000   return ret.retn();
6001 }
6002
6003 /*!
6004  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6005  * cells. Currently cells of the following types are treated:
6006  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6007  * For a cell of other type an exception is thrown.
6008  * Space dimension of a 2D mesh can be either 2 or 3.
6009  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6010  *          cells and one time, lying on \a this mesh. The caller is to delete this
6011  *          field using decrRef() as it is no more needed. 
6012  *  \throw If the coordinates array is not set.
6013  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6014  *  \throw If the connectivity data array has more than one component.
6015  *  \throw If the connectivity data array has a named component.
6016  *  \throw If the connectivity index data array has more than one component.
6017  *  \throw If the connectivity index data array has a named component.
6018  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6019  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6020  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6021  */
6022 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6023 {
6024   checkCoherency();
6025   int spaceDim=getSpaceDimension();
6026   int meshDim=getMeshDimension();
6027   if(spaceDim!=2 && spaceDim!=3)
6028     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6029   if(meshDim!=2 && meshDim!=3)
6030     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6031   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6032   ret->setMesh(this);
6033   int nbOfCells=getNumberOfCells();
6034   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6035   arr->alloc(nbOfCells,1);
6036   double *pt=arr->getPointer();
6037   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6038   const int *conn=_nodal_connec->getConstPointer();
6039   const int *connI=_nodal_connec_index->getConstPointer();
6040   const double *coo=_coords->getConstPointer();
6041   double tmp[12];
6042   for(int i=0;i<nbOfCells;i++,pt++)
6043     {
6044       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6045       switch(t)
6046         {
6047           case INTERP_KERNEL::NORM_TRI3:
6048             {
6049               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6050               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6051               break;
6052             }
6053           case INTERP_KERNEL::NORM_QUAD4:
6054             {
6055               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6056               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6057               break;
6058             }
6059           case INTERP_KERNEL::NORM_TETRA4:
6060             {
6061               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6062               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6063               break;
6064             }
6065         default:
6066           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6067         }
6068       conn+=connI[i+1]-connI[i];
6069     }
6070   ret->setName("AspectRatio");
6071   ret->synchronizeTimeWithSupport();
6072   return ret.retn();
6073 }
6074
6075 /*!
6076  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6077  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6078  * treated: INTERP_KERNEL::NORM_QUAD4.
6079  * For a cell of other type an exception is thrown.
6080  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6081  *          cells and one time, lying on \a this mesh. The caller is to delete this
6082  *          field using decrRef() as it is no more needed. 
6083  *  \throw If the coordinates array is not set.
6084  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6085  *  \throw If the connectivity data array has more than one component.
6086  *  \throw If the connectivity data array has a named component.
6087  *  \throw If the connectivity index data array has more than one component.
6088  *  \throw If the connectivity index data array has a named component.
6089  *  \throw If \a this->getMeshDimension() != 2.
6090  *  \throw If \a this->getSpaceDimension() != 3.
6091  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6092  */
6093 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6094 {
6095   checkCoherency();
6096   int spaceDim=getSpaceDimension();
6097   int meshDim=getMeshDimension();
6098   if(spaceDim!=3)
6099     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6100   if(meshDim!=2)
6101     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6103   ret->setMesh(this);
6104   int nbOfCells=getNumberOfCells();
6105   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6106   arr->alloc(nbOfCells,1);
6107   double *pt=arr->getPointer();
6108   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6109   const int *conn=_nodal_connec->getConstPointer();
6110   const int *connI=_nodal_connec_index->getConstPointer();
6111   const double *coo=_coords->getConstPointer();
6112   double tmp[12];
6113   for(int i=0;i<nbOfCells;i++,pt++)
6114     {
6115       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6116       switch(t)
6117         {
6118           case INTERP_KERNEL::NORM_QUAD4:
6119             {
6120               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6121               *pt=INTERP_KERNEL::quadWarp(tmp);
6122               break;
6123             }
6124         default:
6125           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6126         }
6127       conn+=connI[i+1]-connI[i];
6128     }
6129   ret->setName("Warp");
6130   ret->synchronizeTimeWithSupport();
6131   return ret.retn();
6132 }
6133
6134
6135 /*!
6136  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6137  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6138  * treated: INTERP_KERNEL::NORM_QUAD4.
6139  * For a cell of other type an exception is thrown.
6140  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6141  *          cells and one time, lying on \a this mesh. The caller is to delete this
6142  *          field using decrRef() as it is no more needed. 
6143  *  \throw If the coordinates array is not set.
6144  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6145  *  \throw If the connectivity data array has more than one component.
6146  *  \throw If the connectivity data array has a named component.
6147  *  \throw If the connectivity index data array has more than one component.
6148  *  \throw If the connectivity index data array has a named component.
6149  *  \throw If \a this->getMeshDimension() != 2.
6150  *  \throw If \a this->getSpaceDimension() != 3.
6151  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6152  */
6153 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6154 {
6155   checkCoherency();
6156   int spaceDim=getSpaceDimension();
6157   int meshDim=getMeshDimension();
6158   if(spaceDim!=3)
6159     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6160   if(meshDim!=2)
6161     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6162   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6163   ret->setMesh(this);
6164   int nbOfCells=getNumberOfCells();
6165   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6166   arr->alloc(nbOfCells,1);
6167   double *pt=arr->getPointer();
6168   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6169   const int *conn=_nodal_connec->getConstPointer();
6170   const int *connI=_nodal_connec_index->getConstPointer();
6171   const double *coo=_coords->getConstPointer();
6172   double tmp[12];
6173   for(int i=0;i<nbOfCells;i++,pt++)
6174     {
6175       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6176       switch(t)
6177         {
6178           case INTERP_KERNEL::NORM_QUAD4:
6179             {
6180               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6181               *pt=INTERP_KERNEL::quadSkew(tmp);
6182               break;
6183             }
6184         default:
6185           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6186         }
6187       conn+=connI[i+1]-connI[i];
6188     }
6189   ret->setName("Skew");
6190   ret->synchronizeTimeWithSupport();
6191   return ret.retn();
6192 }
6193
6194 /*!
6195  * This method aggregate the bbox of each cell and put it into bbox parameter.
6196  * 
6197  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6198  * 
6199  * \throw If \a this is not fully set (coordinates and connectivity).
6200  * \throw If a cell in \a this has no valid nodeId.
6201  */
6202 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree() const
6203 {
6204   checkFullyDefined();
6205   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6206   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6207   double *bbox(ret->getPointer());
6208   for(int i=0;i<nbOfCells*spaceDim;i++)
6209     {
6210       bbox[2*i]=std::numeric_limits<double>::max();
6211       bbox[2*i+1]=-std::numeric_limits<double>::max();
6212     }
6213   const double *coordsPtr(_coords->getConstPointer());
6214   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6215   for(int i=0;i<nbOfCells;i++)
6216     {
6217       int offset=connI[i]+1;
6218       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6219       for(int j=0;j<nbOfNodesForCell;j++)
6220         {
6221           int nodeId=conn[offset+j];
6222           if(nodeId>=0 && nodeId<nbOfNodes)
6223             {
6224               for(int k=0;k<spaceDim;k++)
6225                 {
6226                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6227                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6228                 }
6229               kk++;
6230             }
6231         }
6232       if(kk==0)
6233         {
6234           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6235           throw INTERP_KERNEL::Exception(oss.str().c_str());
6236         }
6237     }
6238   return ret.retn();
6239 }
6240
6241 /// @cond INTERNAL
6242
6243 namespace ParaMEDMEMImpl
6244 {
6245   class ConnReader
6246   {
6247   public:
6248     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6249     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6250   private:
6251     const int *_conn;
6252     int _val;
6253   };
6254
6255   class ConnReader2
6256   {
6257   public:
6258     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6259     bool operator() (const int& pos) { return _conn[pos]==_val; }
6260   private:
6261     const int *_conn;
6262     int _val;
6263   };
6264 }
6265
6266 /// @endcond
6267
6268 /*!
6269  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6270  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6271  * \a this is composed in cell types.
6272  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6273  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6274  * This parameter is kept only for compatibility with other methode listed above.
6275  */
6276 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6277 {
6278   checkConnectivityFullyDefined();
6279   const int *conn=_nodal_connec->getConstPointer();
6280   const int *connI=_nodal_connec_index->getConstPointer();
6281   const int *work=connI;
6282   int nbOfCells=getNumberOfCells();
6283   std::size_t n=getAllTypes().size();
6284   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6285   std::set<INTERP_KERNEL::NormalizedCellType> types;
6286   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6287     {
6288       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6289       if(types.find(typ)!=types.end())
6290         {
6291           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6292           oss << " is not contiguous !";
6293           throw INTERP_KERNEL::Exception(oss.str().c_str());
6294         }
6295       types.insert(typ);
6296       ret[3*i]=typ;
6297       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6298       ret[3*i+1]=(int)std::distance(work,work2);
6299       work=work2;
6300     }
6301   return ret;
6302 }
6303
6304 /*!
6305  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6306  * only for types cell, type node is not managed.
6307  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6308  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6309  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6310  * If 2 or more same geometric type is in \a code and exception is thrown too.
6311  *
6312  * This method firstly checks
6313  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6314  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6315  * an exception is thrown too.
6316  * 
6317  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6318  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6319  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6320  */
6321 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6322 {
6323   if(code.empty())
6324     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6325   std::size_t sz=code.size();
6326   std::size_t n=sz/3;
6327   if(sz%3!=0)
6328     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6329   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6330   int nb=0;
6331   bool isNoPflUsed=true;
6332   for(std::size_t i=0;i<n;i++)
6333     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6334       {
6335         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6336         nb+=code[3*i+1];
6337         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6338           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6339         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6340       }
6341   if(types.size()!=n)
6342     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6343   if(isNoPflUsed)
6344     {
6345       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6346         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6347       if(types.size()==_types.size())
6348         return 0;
6349     }
6350   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6351   ret->alloc(nb,1);
6352   int *retPtr=ret->getPointer();
6353   const int *connI=_nodal_connec_index->getConstPointer();
6354   const int *conn=_nodal_connec->getConstPointer();
6355   int nbOfCells=getNumberOfCells();
6356   const int *i=connI;
6357   int kk=0;
6358   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6359     {
6360       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6361       int offset=(int)std::distance(connI,i);
6362       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6363       int nbOfCellsOfCurType=(int)std::distance(i,j);
6364       if(code[3*kk+2]==-1)
6365         for(int k=0;k<nbOfCellsOfCurType;k++)
6366           *retPtr++=k+offset;
6367       else
6368         {
6369           int idInIdsPerType=code[3*kk+2];
6370           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6371             {
6372               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6373               if(zePfl)
6374                 {
6375                   zePfl->checkAllocated();
6376                   if(zePfl->getNumberOfComponents()==1)
6377                     {
6378                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6379                         {
6380                           if(*k>=0 && *k<nbOfCellsOfCurType)
6381                             *retPtr=(*k)+offset;
6382                           else
6383                             {
6384                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6385                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6386                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6387                             }
6388                         }
6389                     }
6390                   else
6391                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6392                 }
6393               else
6394                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6395             }
6396           else
6397             {
6398               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6399               oss << " should be in [0," << idsPerType.size() << ") !";
6400               throw INTERP_KERNEL::Exception(oss.str().c_str());
6401             }
6402         }
6403       i=j;
6404     }
6405   return ret.retn();
6406 }
6407
6408 /*!
6409  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6410  * 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.
6411  * 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.
6412  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6413  * 
6414  * \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.
6415  * \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,
6416  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6417  * \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.
6418  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6419  * \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
6420  */
6421 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6422 {
6423   if(!profile)
6424     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6425   if(profile->getNumberOfComponents()!=1)
6426     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6427   checkConnectivityFullyDefined();
6428   const int *conn=_nodal_connec->getConstPointer();
6429   const int *connI=_nodal_connec_index->getConstPointer();
6430   int nbOfCells=getNumberOfCells();
6431   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6432   std::vector<int> typeRangeVals(1);
6433   for(const int *i=connI;i!=connI+nbOfCells;)
6434     {
6435       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6436       if(std::find(types.begin(),types.end(),curType)!=types.end())
6437         {
6438           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6439         }
6440       types.push_back(curType);
6441       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6442       typeRangeVals.push_back((int)std::distance(connI,i));
6443     }
6444   //
6445   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6446   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6447   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6448   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6449   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6450   //
6451   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6452   code.resize(3*nbOfCastsFinal);
6453   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6454   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6455   for(int i=0;i<nbOfCastsFinal;i++)
6456     {
6457       int castId=castsPresent->getIJ(i,0);
6458       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6459       idsInPflPerType2.push_back(tmp3);
6460       code[3*i]=(int)types[castId];
6461       code[3*i+1]=tmp3->getNumberOfTuples();
6462       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6463       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6464         {
6465           tmp4->copyStringInfoFrom(*profile);
6466           idsPerType2.push_back(tmp4);
6467           code[3*i+2]=(int)idsPerType2.size()-1;
6468         }
6469       else
6470         {
6471           code[3*i+2]=-1;
6472         }
6473     }
6474   std::size_t sz2=idsInPflPerType2.size();
6475   idsInPflPerType.resize(sz2);
6476   for(std::size_t i=0;i<sz2;i++)
6477     {
6478       DataArrayInt *locDa=idsInPflPerType2[i];
6479       locDa->incrRef();
6480       idsInPflPerType[i]=locDa;
6481     }
6482   std::size_t sz=idsPerType2.size();
6483   idsPerType.resize(sz);
6484   for(std::size_t i=0;i<sz;i++)
6485     {
6486       DataArrayInt *locDa=idsPerType2[i];
6487       locDa->incrRef();
6488       idsPerType[i]=locDa;
6489     }
6490 }
6491
6492 /*!
6493  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6494  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6495  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6496  * 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.
6497  */
6498 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6499 {
6500   checkFullyDefined();
6501   nM1LevMesh->checkFullyDefined();
6502   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6503     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6504   if(_coords!=nM1LevMesh->getCoords())
6505     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6506   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6507   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6508   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6509   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6510   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6511   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6512   tmp->setConnectivity(tmp0,tmp1);
6513   tmp->renumberCells(ret0->getConstPointer(),false);
6514   revDesc=tmp->getNodalConnectivity();
6515   revDescIndx=tmp->getNodalConnectivityIndex();
6516   DataArrayInt *ret=0;
6517   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6518     {
6519       int tmp2;
6520       ret->getMaxValue(tmp2);
6521       ret->decrRef();
6522       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6523       throw INTERP_KERNEL::Exception(oss.str().c_str());
6524     }
6525   nM1LevMeshIds=ret;
6526   //
6527   revDesc->incrRef();
6528   revDescIndx->incrRef();
6529   ret1->incrRef();
6530   ret0->incrRef();
6531   meshnM1Old2New=ret0;
6532   return ret1;
6533 }
6534
6535 /*!
6536  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6537  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6538  * in "Old to New" mode.
6539  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6540  *          this array using decrRef() as it is no more needed.
6541  *  \throw If the nodal connectivity of cells is not defined.
6542  */
6543 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6544 {
6545   checkConnectivityFullyDefined();
6546   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6547   renumberCells(ret->getConstPointer(),false);
6548   return ret.retn();
6549 }
6550
6551 /*!
6552  * This methods checks that cells are sorted by their types.
6553  * This method makes asumption (no check) that connectivity is correctly set before calling.
6554  */
6555 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6556 {
6557   checkFullyDefined();
6558   const int *conn=_nodal_connec->getConstPointer();
6559   const int *connI=_nodal_connec_index->getConstPointer();
6560   int nbOfCells=getNumberOfCells();
6561   std::set<INTERP_KERNEL::NormalizedCellType> types;
6562   for(const int *i=connI;i!=connI+nbOfCells;)
6563     {
6564       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6565       if(types.find(curType)!=types.end())
6566         return false;
6567       types.insert(curType);
6568       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6569     }
6570   return true;
6571 }
6572
6573 /*!
6574  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6575  * The geometric type order is specified by MED file.
6576  * 
6577  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6578  */
6579 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6580 {
6581   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6582 }
6583
6584 /*!
6585  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6586  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6587  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6588  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6589  */
6590 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6591 {
6592   checkFullyDefined();
6593   const int *conn=_nodal_connec->getConstPointer();
6594   const int *connI=_nodal_connec_index->getConstPointer();
6595   int nbOfCells=getNumberOfCells();
6596   if(nbOfCells==0)
6597     return true;
6598   int lastPos=-1;
6599   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6600   for(const int *i=connI;i!=connI+nbOfCells;)
6601     {
6602       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6603       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6604       if(isTypeExists!=orderEnd)
6605         {
6606           int pos=(int)std::distance(orderBg,isTypeExists);
6607           if(pos<=lastPos)
6608             return false;
6609           lastPos=pos;
6610           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6611         }
6612       else
6613         {
6614           if(sg.find(curType)==sg.end())
6615             {
6616               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6617               sg.insert(curType);
6618             }
6619           else
6620             return false;
6621         }
6622     }
6623   return true;
6624 }
6625
6626 /*!
6627  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6628  * 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
6629  * 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'.
6630  */
6631 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6632 {
6633   checkConnectivityFullyDefined();
6634   int nbOfCells=getNumberOfCells();
6635   const int *conn=_nodal_connec->getConstPointer();
6636   const int *connI=_nodal_connec_index->getConstPointer();
6637   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6639   tmpa->alloc(nbOfCells,1);
6640   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6641   tmpb->fillWithZero();
6642   int *tmp=tmpa->getPointer();
6643   int *tmp2=tmpb->getPointer();
6644   for(const int *i=connI;i!=connI+nbOfCells;i++)
6645     {
6646       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6647       if(where!=orderEnd)
6648         {
6649           int pos=(int)std::distance(orderBg,where);
6650           tmp2[pos]++;
6651           tmp[std::distance(connI,i)]=pos;
6652         }
6653       else
6654         {
6655           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6656           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6657           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6658           throw INTERP_KERNEL::Exception(oss.str().c_str());
6659         }
6660     }
6661   nbPerType=tmpb.retn();
6662   return tmpa.retn();
6663 }
6664
6665 /*!
6666  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6667  *
6668  * \return a new object containing the old to new correspondance.
6669  *
6670  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6671  */
6672 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6673 {
6674   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6675 }
6676
6677 /*!
6678  * 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.
6679  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6680  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6681  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6682  */
6683 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6684 {
6685   DataArrayInt *nbPerType=0;
6686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6687   nbPerType->decrRef();
6688   return tmpa->buildPermArrPerLevel();
6689 }
6690
6691 /*!
6692  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6693  * The number of cells remains unchanged after the call of this method.
6694  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6695  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6696  *
6697  * \return the array giving the correspondance old to new.
6698  */
6699 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6700 {
6701   checkFullyDefined();
6702   computeTypes();
6703   const int *conn=_nodal_connec->getConstPointer();
6704   const int *connI=_nodal_connec_index->getConstPointer();
6705   int nbOfCells=getNumberOfCells();
6706   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6707   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6708     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6709       {
6710         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6711         types.push_back(curType);
6712         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6713       }
6714   DataArrayInt *ret=DataArrayInt::New();
6715   ret->alloc(nbOfCells,1);
6716   int *retPtr=ret->getPointer();
6717   std::fill(retPtr,retPtr+nbOfCells,-1);
6718   int newCellId=0;
6719   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6720     {
6721       for(const int *i=connI;i!=connI+nbOfCells;i++)
6722         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6723           retPtr[std::distance(connI,i)]=newCellId++;
6724     }
6725   renumberCells(retPtr,false);
6726   return ret;
6727 }
6728
6729 /*!
6730  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6731  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6732  * This method makes asumption that connectivity is correctly set before calling.
6733  */
6734 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6735 {
6736   checkConnectivityFullyDefined();
6737   const int *conn=_nodal_connec->getConstPointer();
6738   const int *connI=_nodal_connec_index->getConstPointer();
6739   int nbOfCells=getNumberOfCells();
6740   std::vector<MEDCouplingUMesh *> ret;
6741   for(const int *i=connI;i!=connI+nbOfCells;)
6742     {
6743       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6744       int beginCellId=(int)std::distance(connI,i);
6745       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6746       int endCellId=(int)std::distance(connI,i);
6747       int sz=endCellId-beginCellId;
6748       int *cells=new int[sz];
6749       for(int j=0;j<sz;j++)
6750         cells[j]=beginCellId+j;
6751       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6752       delete [] cells;
6753       ret.push_back(m);
6754     }
6755   return ret;
6756 }
6757
6758 /*!
6759  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6760  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6761  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6762  *
6763  * \return a newly allocated instance, that the caller must manage.
6764  * \throw If \a this contains more than one geometric type.
6765  * \throw If the nodal connectivity of \a this is not fully defined.
6766  * \throw If the internal data is not coherent.
6767  */
6768 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6769 {
6770   checkConnectivityFullyDefined();
6771     if(_types.size()!=1)
6772     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6773   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6774   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6775   ret->setCoords(getCoords());
6776   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6777   if(retC)
6778     {
6779       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6780       retC->setNodalConnectivity(c);
6781     }
6782   else
6783     {
6784       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6785       if(!retD)
6786         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6787       DataArrayInt *c=0,*ci=0;
6788       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6789       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6790       retD->setNodalConnectivity(cs,cis);
6791     }
6792   return ret.retn();
6793 }
6794
6795 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6796 {
6797   checkConnectivityFullyDefined();
6798     if(_types.size()!=1)
6799     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6800   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6801   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6802   if(cm.isDynamic())
6803     {
6804       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6805       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6806       throw INTERP_KERNEL::Exception(oss.str().c_str());
6807     }
6808   int nbCells=getNumberOfCells();
6809   int typi=(int)typ;
6810   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6812   int *outPtr=connOut->getPointer();
6813   const int *conn=_nodal_connec->begin();
6814   const int *connI=_nodal_connec_index->begin();
6815   nbNodesPerCell++;
6816   for(int i=0;i<nbCells;i++,connI++)
6817     {
6818       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6819         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6820       else
6821         {
6822           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 << ") !";
6823           throw INTERP_KERNEL::Exception(oss.str().c_str());
6824         }
6825     }
6826   return connOut.retn();
6827 }
6828
6829 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
6830 {
6831   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6832   checkConnectivityFullyDefined();
6833   if(_types.size()!=1)
6834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6835   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6836   if(lgth<nbCells)
6837     throw INTERP_KERNEL::Exception(msg0);
6838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6839   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6840   int *cp(c->getPointer()),*cip(ci->getPointer());
6841   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6842   cip[0]=0;
6843   for(int i=0;i<nbCells;i++,cip++,incip++)
6844     {
6845       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6846       int delta(stop-strt);
6847       if(delta>=1)
6848         {
6849           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6850             cp=std::copy(incp+strt,incp+stop,cp);
6851           else
6852             throw INTERP_KERNEL::Exception(msg0);
6853         }
6854       else
6855         throw INTERP_KERNEL::Exception(msg0);
6856       cip[1]=cip[0]+delta;
6857     }
6858   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6859 }
6860
6861 /*!
6862  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6863  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6864  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6865  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6866  * are not used here to avoid the build of big permutation array.
6867  *
6868  * \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
6869  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6870  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6871  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6872  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6873  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6874  * \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
6875  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6876  */
6877 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6878                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6879                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6880 {
6881   std::vector<const MEDCouplingUMesh *> ms2;
6882   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6883     if(*it)
6884       {
6885         (*it)->checkConnectivityFullyDefined();
6886         ms2.push_back(*it);
6887       }
6888   if(ms2.empty())
6889     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6890   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6891   int meshDim=ms2[0]->getMeshDimension();
6892   std::vector<const MEDCouplingUMesh *> m1ssm;
6893   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6894   //
6895   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6896   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6897   int fake=0,rk=0;
6898   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6899   ret1->alloc(0,1); ret2->alloc(0,1);
6900   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6901     {
6902       if(meshDim!=(*it)->getMeshDimension())
6903         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6904       if(refCoo!=(*it)->getCoords())
6905         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6906       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6907       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6908       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6909       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6910         {
6911           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6912           m1ssmSingleAuto.push_back(singleCell);
6913           m1ssmSingle.push_back(singleCell);
6914           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6915         }
6916     }
6917   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6918   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6919   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6920   for(std::size_t i=0;i<m1ssm.size();i++)
6921     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6922   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6923   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6924   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6925   return ret0.retn();
6926 }
6927
6928 /*!
6929  * This method returns a newly created DataArrayInt instance.
6930  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6931  */
6932 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
6933 {
6934   checkFullyDefined();
6935   const int *conn=_nodal_connec->getConstPointer();
6936   const int *connIndex=_nodal_connec_index->getConstPointer();
6937   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6938   for(const int *w=begin;w!=end;w++)
6939     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6940       ret->pushBackSilent(*w);
6941   return ret.retn();
6942 }
6943
6944 /*!
6945  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6946  * are in [0:getNumberOfCells())
6947  */
6948 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
6949 {
6950   checkFullyDefined();
6951   const int *conn=_nodal_connec->getConstPointer();
6952   const int *connI=_nodal_connec_index->getConstPointer();
6953   int nbOfCells=getNumberOfCells();
6954   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6955   int *tmp=new int[nbOfCells];
6956   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6957     {
6958       int j=0;
6959       for(const int *i=connI;i!=connI+nbOfCells;i++)
6960         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6961           tmp[std::distance(connI,i)]=j++;
6962     }
6963   DataArrayInt *ret=DataArrayInt::New();
6964   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6965   ret->copyStringInfoFrom(*da);
6966   int *retPtr=ret->getPointer();
6967   const int *daPtr=da->getConstPointer();
6968   int nbOfElems=da->getNbOfElems();
6969   for(int k=0;k<nbOfElems;k++)
6970     retPtr[k]=tmp[daPtr[k]];
6971   delete [] tmp;
6972   return ret;
6973 }
6974
6975 /*!
6976  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6977  * This method \b works \b for mesh sorted by type.
6978  * cells whose ids is in 'idsPerGeoType' array.
6979  * This method conserves coords and name of mesh.
6980  */
6981 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6982 {
6983   std::vector<int> code=getDistributionOfTypes();
6984   std::size_t nOfTypesInThis=code.size()/3;
6985   int sz=0,szOfType=0;
6986   for(std::size_t i=0;i<nOfTypesInThis;i++)
6987     {
6988       if(code[3*i]!=type)
6989         sz+=code[3*i+1];
6990       else
6991         szOfType=code[3*i+1];
6992     }
6993   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6994     if(*work<0 || *work>=szOfType)
6995       {
6996         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6997         oss << ". It should be in [0," << szOfType << ") !";
6998         throw INTERP_KERNEL::Exception(oss.str().c_str());
6999       }
7000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7001   int *idsPtr=idsTokeep->getPointer();
7002   int offset=0;
7003   for(std::size_t i=0;i<nOfTypesInThis;i++)
7004     {
7005       if(code[3*i]!=type)
7006         for(int j=0;j<code[3*i+1];j++)
7007           *idsPtr++=offset+j;
7008       else
7009         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7010       offset+=code[3*i+1];
7011     }
7012   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7013   ret->copyTinyInfoFrom(this);
7014   return ret.retn();
7015 }
7016
7017 /*!
7018  * This method returns a vector of size 'this->getNumberOfCells()'.
7019  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7020  */
7021 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7022 {
7023   int ncell=getNumberOfCells();
7024   std::vector<bool> ret(ncell);
7025   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7026   const int *c=getNodalConnectivity()->getConstPointer();
7027   for(int i=0;i<ncell;i++)
7028     {
7029       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7030       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7031       ret[i]=cm.isQuadratic();
7032     }
7033   return ret;
7034 }
7035
7036 /*!
7037  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7038  */
7039 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7040 {
7041   if(other->getType()!=UNSTRUCTURED)
7042     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7043   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7044   return MergeUMeshes(this,otherC);
7045 }
7046
7047 /*!
7048  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7049  * computed by averaging coordinates of cell nodes, so this method is not a right
7050  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7051  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7052  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7053  *          components. The caller is to delete this array using decrRef() as it is
7054  *          no more needed.
7055  *  \throw If the coordinates array is not set.
7056  *  \throw If the nodal connectivity of cells is not defined.
7057  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7058  */
7059 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7060 {
7061   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7062   int spaceDim=getSpaceDimension();
7063   int nbOfCells=getNumberOfCells();
7064   ret->alloc(nbOfCells,spaceDim);
7065   ret->copyStringInfoFrom(*getCoords());
7066   double *ptToFill=ret->getPointer();
7067   const int *nodal=_nodal_connec->getConstPointer();
7068   const int *nodalI=_nodal_connec_index->getConstPointer();
7069   const double *coor=_coords->getConstPointer();
7070   for(int i=0;i<nbOfCells;i++)
7071     {
7072       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7073       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7074       ptToFill+=spaceDim;
7075     }
7076   return ret.retn();
7077 }
7078
7079 /*!
7080  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7081  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7082  * 
7083  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7084  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7085  * 
7086  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7087  * \throw If \a this is not fully defined (coordinates and connectivity)
7088  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7089  */
7090 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7091 {
7092   checkFullyDefined();
7093   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7094   int spaceDim=getSpaceDimension();
7095   int nbOfCells=getNumberOfCells();
7096   int nbOfNodes=getNumberOfNodes();
7097   ret->alloc(nbOfCells,spaceDim);
7098   double *ptToFill=ret->getPointer();
7099   const int *nodal=_nodal_connec->getConstPointer();
7100   const int *nodalI=_nodal_connec_index->getConstPointer();
7101   const double *coor=_coords->getConstPointer();
7102   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7103     {
7104       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7105       std::fill(ptToFill,ptToFill+spaceDim,0.);
7106       if(type!=INTERP_KERNEL::NORM_POLYHED)
7107         {
7108           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7109             {
7110               if(*conn>=0 && *conn<nbOfNodes)
7111                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7112               else
7113                 {
7114                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7115                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7116                 }
7117             }
7118           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7119           if(nbOfNodesInCell>0)
7120             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7121           else
7122             {
7123               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7124               throw INTERP_KERNEL::Exception(oss.str().c_str());
7125             }
7126         }
7127       else
7128         {
7129           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7130           s.erase(-1);
7131           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7132             {
7133               if(*it>=0 && *it<nbOfNodes)
7134                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7135               else
7136                 {
7137                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7138                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7139                 }
7140             }
7141           if(!s.empty())
7142             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7143           else
7144             {
7145               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7146               throw INTERP_KERNEL::Exception(oss.str().c_str());
7147             }
7148         }
7149     }
7150   return ret.retn();
7151 }
7152
7153 /*!
7154  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7155  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7156  * are specified via an array of cell ids. 
7157  *  \warning Validity of the specified cell ids is not checked! 
7158  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7159  *  \param [in] begin - an array of cell ids of interest.
7160  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7161  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7162  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7163  *          caller is to delete this array using decrRef() as it is no more needed. 
7164  *  \throw If the coordinates array is not set.
7165  *  \throw If the nodal connectivity of cells is not defined.
7166  *
7167  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7168  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7169  */
7170 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7171 {
7172   DataArrayDouble *ret=DataArrayDouble::New();
7173   int spaceDim=getSpaceDimension();
7174   int nbOfTuple=(int)std::distance(begin,end);
7175   ret->alloc(nbOfTuple,spaceDim);
7176   double *ptToFill=ret->getPointer();
7177   double *tmp=new double[spaceDim];
7178   const int *nodal=_nodal_connec->getConstPointer();
7179   const int *nodalI=_nodal_connec_index->getConstPointer();
7180   const double *coor=_coords->getConstPointer();
7181   for(const int *w=begin;w!=end;w++)
7182     {
7183       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7184       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7185       ptToFill+=spaceDim;
7186     }
7187   delete [] tmp;
7188   return ret;
7189 }
7190
7191 /*!
7192  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7193  * 
7194  */
7195 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7196 {
7197   if(!da)
7198     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7199   da->checkAllocated();
7200   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7201   ret->setCoords(da);
7202   int nbOfTuples=da->getNumberOfTuples();
7203   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7204   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7205   c->alloc(2*nbOfTuples,1);
7206   cI->alloc(nbOfTuples+1,1);
7207   int *cp=c->getPointer();
7208   int *cip=cI->getPointer();
7209   *cip++=0;
7210   for(int i=0;i<nbOfTuples;i++)
7211     {
7212       *cp++=INTERP_KERNEL::NORM_POINT1;
7213       *cp++=i;
7214       *cip++=2*(i+1);
7215     }
7216   ret->setConnectivity(c,cI,true);
7217   return ret.retn();
7218 }
7219 /*!
7220  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7221  * Cells and nodes of
7222  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7223  *  \param [in] mesh1 - the first mesh.
7224  *  \param [in] mesh2 - the second mesh.
7225  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7226  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7227  *          is no more needed.
7228  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7229  *  \throw If the coordinates array is not set in none of the meshes.
7230  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7231  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7232  */
7233 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7234 {
7235   std::vector<const MEDCouplingUMesh *> tmp(2);
7236   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7237   return MergeUMeshes(tmp);
7238 }
7239
7240 /*!
7241  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7242  * Cells and nodes of
7243  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7244  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7245  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7246  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7247  *          is no more needed.
7248  *  \throw If \a a.size() == 0.
7249  *  \throw If \a a[ *i* ] == NULL.
7250  *  \throw If the coordinates array is not set in none of the meshes.
7251  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7252  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7253 */
7254 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7255 {
7256   std::size_t sz=a.size();
7257   if(sz==0)
7258     return MergeUMeshesLL(a);
7259   for(std::size_t ii=0;ii<sz;ii++)
7260     if(!a[ii])
7261       {
7262         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7263         throw INTERP_KERNEL::Exception(oss.str().c_str());
7264       }
7265   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7266   std::vector< const MEDCouplingUMesh * > aa(sz);
7267   int spaceDim=-3;
7268   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7269     {
7270       const MEDCouplingUMesh *cur=a[i];
7271       const DataArrayDouble *coo=cur->getCoords();
7272       if(coo)
7273         spaceDim=coo->getNumberOfComponents();
7274     }
7275   if(spaceDim==-3)
7276     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7277   for(std::size_t i=0;i<sz;i++)
7278     {
7279       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7280       aa[i]=bb[i];
7281     }
7282   return MergeUMeshesLL(aa);
7283 }
7284
7285 /// @cond INTERNAL
7286
7287 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7288 {
7289   if(a.empty())
7290     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7291   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7292   int meshDim=(*it)->getMeshDimension();
7293   int nbOfCells=(*it)->getNumberOfCells();
7294   int meshLgth=(*it++)->getMeshLength();
7295   for(;it!=a.end();it++)
7296     {
7297       if(meshDim!=(*it)->getMeshDimension())
7298         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7299       nbOfCells+=(*it)->getNumberOfCells();
7300       meshLgth+=(*it)->getMeshLength();
7301     }
7302   std::vector<const MEDCouplingPointSet *> aps(a.size());
7303   std::copy(a.begin(),a.end(),aps.begin());
7304   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7305   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7306   ret->setCoords(pts);
7307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7308   c->alloc(meshLgth,1);
7309   int *cPtr=c->getPointer();
7310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7311   cI->alloc(nbOfCells+1,1);
7312   int *cIPtr=cI->getPointer();
7313   *cIPtr++=0;
7314   int offset=0;
7315   int offset2=0;
7316   for(it=a.begin();it!=a.end();it++)
7317     {
7318       int curNbOfCell=(*it)->getNumberOfCells();
7319       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7320       const int *curC=(*it)->_nodal_connec->getConstPointer();
7321       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7322       for(int j=0;j<curNbOfCell;j++)
7323         {
7324           const int *src=curC+curCI[j];
7325           *cPtr++=*src++;
7326           for(;src!=curC+curCI[j+1];src++,cPtr++)
7327             {
7328               if(*src!=-1)
7329                 *cPtr=*src+offset2;
7330               else
7331                 *cPtr=-1;
7332             }
7333         }
7334       offset+=curCI[curNbOfCell];
7335       offset2+=(*it)->getNumberOfNodes();
7336     }
7337   //
7338   ret->setConnectivity(c,cI,true);
7339   return ret.retn();
7340 }
7341
7342 /// @endcond
7343
7344 /*!
7345  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7346  * dimension and sharing the node coordinates array.
7347  * All cells of the first mesh precede all cells of the second mesh
7348  * within the result mesh. 
7349  *  \param [in] mesh1 - the first mesh.
7350  *  \param [in] mesh2 - the second mesh.
7351  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7352  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7353  *          is no more needed.
7354  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7355  *  \throw If the meshes do not share the node coordinates array.
7356  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7357  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7358  */
7359 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7360 {
7361   std::vector<const MEDCouplingUMesh *> tmp(2);
7362   tmp[0]=mesh1; tmp[1]=mesh2;
7363   return MergeUMeshesOnSameCoords(tmp);
7364 }
7365
7366 /*!
7367  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7368  * dimension and sharing the node coordinates array.
7369  * All cells of the *i*-th mesh precede all cells of the
7370  * (*i*+1)-th mesh within the result mesh.
7371  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7372  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7373  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7374  *          is no more needed.
7375  *  \throw If \a a.size() == 0.
7376  *  \throw If \a a[ *i* ] == NULL.
7377  *  \throw If the meshes do not share the node coordinates array.
7378  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7379  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7380  */
7381 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7382 {
7383   if(meshes.empty())
7384     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7385   for(std::size_t ii=0;ii<meshes.size();ii++)
7386     if(!meshes[ii])
7387       {
7388         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7389         throw INTERP_KERNEL::Exception(oss.str().c_str());
7390       }
7391   const DataArrayDouble *coords=meshes.front()->getCoords();
7392   int meshDim=meshes.front()->getMeshDimension();
7393   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7394   int meshLgth=0;
7395   int meshIndexLgth=0;
7396   for(;iter!=meshes.end();iter++)
7397     {
7398       if(coords!=(*iter)->getCoords())
7399         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7400       if(meshDim!=(*iter)->getMeshDimension())
7401         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7402       meshLgth+=(*iter)->getMeshLength();
7403       meshIndexLgth+=(*iter)->getNumberOfCells();
7404     }
7405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7406   nodal->alloc(meshLgth,1);
7407   int *nodalPtr=nodal->getPointer();
7408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7409   nodalIndex->alloc(meshIndexLgth+1,1);
7410   int *nodalIndexPtr=nodalIndex->getPointer();
7411   int offset=0;
7412   for(iter=meshes.begin();iter!=meshes.end();iter++)
7413     {
7414       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7415       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7416       int nbOfCells=(*iter)->getNumberOfCells();
7417       int meshLgth2=(*iter)->getMeshLength();
7418       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7419       if(iter!=meshes.begin())
7420         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7421       else
7422         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7423       offset+=meshLgth2;
7424     }
7425   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7426   ret->setName("merge");
7427   ret->setMeshDimension(meshDim);
7428   ret->setConnectivity(nodal,nodalIndex,true);
7429   ret->setCoords(coords);
7430   return ret;
7431 }
7432
7433 /*!
7434  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7435  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7436  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7437  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7438  * New" mode are returned for each input mesh.
7439  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7440  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7441  *          valid values [0,1,2], see zipConnectivityTraducer().
7442  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7443  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7444  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7445  *          no more needed.
7446  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7447  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7448  *          is no more needed.
7449  *  \throw If \a meshes.size() == 0.
7450  *  \throw If \a meshes[ *i* ] == NULL.
7451  *  \throw If the meshes do not share the node coordinates array.
7452  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7453  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7454  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7455  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7456  */
7457 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7458 {
7459   //All checks are delegated to MergeUMeshesOnSameCoords
7460   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7461   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7462   corr.resize(meshes.size());
7463   std::size_t nbOfMeshes=meshes.size();
7464   int offset=0;
7465   const int *o2nPtr=o2n->getConstPointer();
7466   for(std::size_t i=0;i<nbOfMeshes;i++)
7467     {
7468       DataArrayInt *tmp=DataArrayInt::New();
7469       int curNbOfCells=meshes[i]->getNumberOfCells();
7470       tmp->alloc(curNbOfCells,1);
7471       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7472       offset+=curNbOfCells;
7473       tmp->setName(meshes[i]->getName().c_str());
7474       corr[i]=tmp;
7475     }
7476   return ret.retn();
7477 }
7478
7479 /*!
7480  * Makes all given meshes share the nodal connectivity array. The common connectivity
7481  * array is created by concatenating the connectivity arrays of all given meshes. All
7482  * the given meshes must be of the same space dimension but dimension of cells **can
7483  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7484  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7485  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7486  *  \param [in,out] meshes - a vector of meshes to update.
7487  *  \throw If any of \a meshes is NULL.
7488  *  \throw If the coordinates array is not set in any of \a meshes.
7489  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7490  *  \throw If \a meshes are of different space dimension.
7491  */
7492 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7493 {
7494   std::size_t sz=meshes.size();
7495   if(sz==0 || sz==1)
7496     return;
7497   std::vector< const DataArrayDouble * > coords(meshes.size());
7498   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7499   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7500     {
7501       if((*it))
7502         {
7503           (*it)->checkConnectivityFullyDefined();
7504           const DataArrayDouble *coo=(*it)->getCoords();
7505           if(coo)
7506             *it2=coo;
7507           else
7508             {
7509               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7510               oss << " has no coordinate array defined !";
7511               throw INTERP_KERNEL::Exception(oss.str().c_str());
7512             }
7513         }
7514       else
7515         {
7516           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7517           oss << " is null !";
7518           throw INTERP_KERNEL::Exception(oss.str().c_str());
7519         }
7520     }
7521   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7522   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7523   int offset=(*it)->getNumberOfNodes();
7524   (*it++)->setCoords(res);
7525   for(;it!=meshes.end();it++)
7526     {
7527       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7528       (*it)->setCoords(res);
7529       (*it)->shiftNodeNumbersInConn(offset);
7530       offset+=oldNumberOfNodes;
7531     }
7532 }
7533
7534 /*!
7535  * Merges nodes coincident with a given precision within all given meshes that share
7536  * the nodal connectivity array. The given meshes **can be of different** mesh
7537  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7538  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7539  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7540  *  \param [in,out] meshes - a vector of meshes to update.
7541  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7542  *  \throw If any of \a meshes is NULL.
7543  *  \throw If the \a meshes do not share the same node coordinates array.
7544  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7545  */
7546 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7547 {
7548   if(meshes.empty())
7549     return ;
7550   std::set<const DataArrayDouble *> s;
7551   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7552     {
7553       if(*it)
7554         s.insert((*it)->getCoords());
7555       else
7556         {
7557           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 !";
7558           throw INTERP_KERNEL::Exception(oss.str().c_str());
7559         }
7560     }
7561   if(s.size()!=1)
7562     {
7563       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 !";
7564       throw INTERP_KERNEL::Exception(oss.str().c_str());
7565     }
7566   const DataArrayDouble *coo=*(s.begin());
7567   if(!coo)
7568     return;
7569   //
7570   DataArrayInt *comm,*commI;
7571   coo->findCommonTuples(eps,-1,comm,commI);
7572   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7573   int oldNbOfNodes=coo->getNumberOfTuples();
7574   int newNbOfNodes;
7575   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7576   if(oldNbOfNodes==newNbOfNodes)
7577     return ;
7578   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7579   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7580     {
7581       (*it)->renumberNodesInConn(o2n->getConstPointer());
7582       (*it)->setCoords(newCoords);
7583     } 
7584 }
7585
7586 /*!
7587  * 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.
7588  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7589  * \param isQuad specifies the policy of connectivity.
7590  * @ret in/out parameter in which the result will be append
7591  */
7592 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7593 {
7594   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7595   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7596   ret.push_back(cm.getExtrudedType());
7597   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7598   switch(flatType)
7599     {
7600     case INTERP_KERNEL::NORM_POINT1:
7601       {
7602         ret.push_back(connBg[1]);
7603         ret.push_back(connBg[1]+nbOfNodesPerLev);
7604         break;
7605       }
7606     case INTERP_KERNEL::NORM_SEG2:
7607       {
7608         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7609         ret.insert(ret.end(),conn,conn+4);
7610         break;
7611       }
7612     case INTERP_KERNEL::NORM_SEG3:
7613       {
7614         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7615         ret.insert(ret.end(),conn,conn+8);
7616         break;
7617       }
7618     case INTERP_KERNEL::NORM_QUAD4:
7619       {
7620         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7621         ret.insert(ret.end(),conn,conn+8);
7622         break;
7623       }
7624     case INTERP_KERNEL::NORM_TRI3:
7625       {
7626         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7627         ret.insert(ret.end(),conn,conn+6);
7628         break;
7629       }
7630     case INTERP_KERNEL::NORM_TRI6:
7631       {
7632         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,
7633                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7634         ret.insert(ret.end(),conn,conn+15);
7635         break;
7636       }
7637     case INTERP_KERNEL::NORM_QUAD8:
7638       {
7639         int conn[20]={
7640           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7641           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7642           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7643         };
7644         ret.insert(ret.end(),conn,conn+20);
7645         break;
7646       }
7647     case INTERP_KERNEL::NORM_POLYGON:
7648       {
7649         std::back_insert_iterator< std::vector<int> > ii(ret);
7650         std::copy(connBg+1,connEnd,ii);
7651         *ii++=-1;
7652         std::reverse_iterator<const int *> rConnBg(connEnd);
7653         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7654         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7655         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7656         for(std::size_t i=0;i<nbOfRadFaces;i++)
7657           {
7658             *ii++=-1;
7659             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7660             std::copy(conn,conn+4,ii);
7661           }
7662         break;
7663       }
7664     default:
7665       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7666     }
7667 }
7668
7669 /*!
7670  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7671  */
7672 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7673 {
7674   double v[3]={0.,0.,0.};
7675   std::size_t sz=std::distance(begin,end);
7676   if(isQuadratic)
7677     sz/=2;
7678   for(std::size_t i=0;i<sz;i++)
7679     {
7680       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];
7681       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7682       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7683     }
7684   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7685 }
7686
7687 /*!
7688  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7689  */
7690 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7691 {
7692   std::vector<std::pair<int,int> > edges;
7693   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7694   const int *bgFace=begin;
7695   for(std::size_t i=0;i<nbOfFaces;i++)
7696     {
7697       const int *endFace=std::find(bgFace+1,end,-1);
7698       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7699       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7700         {
7701           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7702           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7703             return false;
7704           edges.push_back(p1);
7705         }
7706       bgFace=endFace+1;
7707     }
7708   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7709 }
7710
7711 /*!
7712  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7713  */
7714 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7715 {
7716   double vec0[3],vec1[3];
7717   std::size_t sz=std::distance(begin,end);
7718   if(sz%2!=0)
7719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7720   int nbOfNodes=(int)sz/2;
7721   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7722   const double *pt0=coords+3*begin[0];
7723   const double *pt1=coords+3*begin[nbOfNodes];
7724   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7725   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7726 }
7727
7728 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7729 {
7730   std::size_t sz=std::distance(begin,end);
7731   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7732   std::size_t nbOfNodes(sz/2);
7733   std::copy(begin,end,(int *)tmp);
7734   for(std::size_t j=1;j<nbOfNodes;j++)
7735     {
7736       begin[j]=tmp[nbOfNodes-j];
7737       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7738     }
7739 }
7740
7741 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7742 {
7743   std::size_t sz=std::distance(begin,end);
7744   if(sz!=4)
7745     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7746   double vec0[3],vec1[3];
7747   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7748   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]; 
7749   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;
7750 }
7751
7752 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7753 {
7754   std::size_t sz=std::distance(begin,end);
7755   if(sz!=5)
7756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7757   double vec0[3];
7758   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7759   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7760   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7761 }
7762
7763 /*!
7764  * 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 ) 
7765  * 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
7766  * a 2D space.
7767  *
7768  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7769  * \param [in] coords the coordinates with nb of components exactly equal to 3
7770  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7771  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7772  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7773  */
7774 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
7775 {
7776   int nbFaces=std::count(begin+1,end,-1)+1;
7777   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7778   double *vPtr=v->getPointer();
7779   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7780   double *pPtr=p->getPointer();
7781   const int *stFaceConn=begin+1;
7782   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7783     {
7784       const int *endFaceConn=std::find(stFaceConn,end,-1);
7785       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7786       stFaceConn=endFaceConn+1;
7787     }
7788   pPtr=p->getPointer(); vPtr=v->getPointer();
7789   DataArrayInt *comm1=0,*commI1=0;
7790   v->findCommonTuples(eps,-1,comm1,commI1);
7791   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7792   const int *comm1Ptr=comm1->getConstPointer();
7793   const int *commI1Ptr=commI1->getConstPointer();
7794   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7795   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7796   //
7797   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7798   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7799   mm->finishInsertingCells();
7800   //
7801   for(int i=0;i<nbOfGrps1;i++)
7802     {
7803       int vecId=comm1Ptr[commI1Ptr[i]];
7804       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7805       DataArrayInt *comm2=0,*commI2=0;
7806       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7807       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7808       const int *comm2Ptr=comm2->getConstPointer();
7809       const int *commI2Ptr=commI2->getConstPointer();
7810       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7811       for(int j=0;j<nbOfGrps2;j++)
7812         {
7813           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7814             {
7815               res->insertAtTheEnd(begin,end);
7816               res->pushBackSilent(-1);
7817             }
7818           else
7819             {
7820               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7821               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7822               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7823               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7824               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7825               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7826               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7827               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7828               const int *idsNodePtr=idsNode->getConstPointer();
7829               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];
7830               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7831               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7832               if(std::abs(norm)>eps)
7833                 {
7834                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7835                   mm3->rotate(center,vec,angle);
7836                 }
7837               mm3->changeSpaceDimension(2);
7838               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7839               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7840               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7841               int nbOfCells=mm4->getNumberOfCells();
7842               for(int k=0;k<nbOfCells;k++)
7843                 {
7844                   int l=0;
7845                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7846                     res->pushBackSilent(idsNodePtr[*work]);
7847                   res->pushBackSilent(-1);
7848                 }
7849             }
7850         }
7851     }
7852   res->popBackSilent();
7853 }
7854
7855 /*!
7856  * 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
7857  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7858  * 
7859  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7860  * \param [in] coords coordinates expected to have 3 components.
7861  * \param [in] begin start of the nodal connectivity of the face.
7862  * \param [in] end end of the nodal connectivity (excluded) of the face.
7863  * \param [out] v the normalized vector of size 3
7864  * \param [out] p the pos of plane
7865  */
7866 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
7867 {
7868   std::size_t nbPoints=std::distance(begin,end);
7869   if(nbPoints<3)
7870     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7871   double vec[3]={0.,0.,0.};
7872   std::size_t j=0;
7873   bool refFound=false;
7874   for(;j<nbPoints-1 && !refFound;j++)
7875     {
7876       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7877       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7878       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7879       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7880       if(norm>eps)
7881         {
7882           refFound=true;
7883           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7884         }
7885     }
7886   for(std::size_t i=j;i<nbPoints-1;i++)
7887     {
7888       double curVec[3];
7889       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7890       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7891       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7892       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7893       if(norm<eps)
7894         continue;
7895       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7896       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];
7897       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7898       if(norm>eps)
7899         {
7900           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7901           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7902           return ;
7903         }
7904     }
7905   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7906 }
7907
7908 /*!
7909  * This method tries to obtain a well oriented polyhedron.
7910  * If the algorithm fails, an exception will be thrown.
7911  */
7912 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
7913 {
7914   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7915   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7916   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7917   isPerm[0]=true;
7918   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7919   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7920   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7921   //
7922   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7923     {
7924       bgFace=begin;
7925       std::size_t smthChanged=0;
7926       for(std::size_t i=0;i<nbOfFaces;i++)
7927         {
7928           endFace=std::find(bgFace+1,end,-1);
7929           nbOfEdgesInFace=std::distance(bgFace,endFace);
7930           if(!isPerm[i])
7931             {
7932               bool b;
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                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7938                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7939                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7940                 }
7941               if(isPerm[i])
7942                 { 
7943                   if(!b)
7944                     std::reverse(bgFace+1,endFace);
7945                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7946                     {
7947                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7948                       std::pair<int,int> p2(p1.second,p1.first);
7949                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7950                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7951                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7952                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7953                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7954                       if(it!=edgesOK.end())
7955                         {
7956                           edgesOK.erase(it);
7957                           edgesFinished.push_back(p1);
7958                         }
7959                       else
7960                         edgesOK.push_back(p1);
7961                     }
7962                 }
7963             }
7964           bgFace=endFace+1;
7965         }
7966       if(smthChanged==0)
7967         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7968     }
7969   if(!edgesOK.empty())
7970     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7971   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7972     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7973       bgFace=begin;
7974       for(std::size_t i=0;i<nbOfFaces;i++)
7975         {
7976           endFace=std::find(bgFace+1,end,-1);
7977           std::reverse(bgFace+1,endFace);
7978           bgFace=endFace+1;
7979         }
7980     }
7981 }
7982
7983 /*!
7984  * This method makes the assumption spacedimension == meshdimension == 2.
7985  * This method works only for linear cells.
7986  * 
7987  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7988  */
7989 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
7990 {
7991   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7992     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7993   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7994   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7995   int nbOfNodesExpected=m->getNumberOfNodes();
7996   if(m->getNumberOfCells()!=nbOfNodesExpected)
7997     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7998   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7999   const int *n2oPtr=n2o->getConstPointer();
8000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8001   m->getReverseNodalConnectivity(revNodal,revNodalI);
8002   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8003   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8004   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8005   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8006   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
8007   if(nbOfNodesExpected<1)
8008     return ret.retn();
8009   int prevCell=0;
8010   int prevNode=nodalPtr[nodalIPtr[0]+1];
8011   *work++=n2oPtr[prevNode];
8012   for(int i=1;i<nbOfNodesExpected;i++)
8013     {
8014       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8015         {
8016           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8017           conn.erase(prevNode);
8018           if(conn.size()==1)
8019             {
8020               int curNode=*(conn.begin());
8021               *work++=n2oPtr[curNode];
8022               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8023               shar.erase(prevCell);
8024               if(shar.size()==1)
8025                 {
8026                   prevCell=*(shar.begin());
8027                   prevNode=curNode;
8028                 }
8029               else
8030                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8031             }
8032           else
8033             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8034         }
8035       else
8036         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8037     }
8038   return ret.retn();
8039 }
8040
8041 /*!
8042  * This method makes the assumption spacedimension == meshdimension == 3.
8043  * This method works only for linear cells.
8044  * 
8045  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8046  */
8047 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8048 {
8049   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8050     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8051   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8052   const int *conn=m->getNodalConnectivity()->getConstPointer();
8053   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8054   int nbOfCells=m->getNumberOfCells();
8055   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8056   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8057   if(nbOfCells<1)
8058     return ret.retn();
8059   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8060   for(int i=1;i<nbOfCells;i++)
8061     {
8062       *work++=-1;
8063       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8064     }
8065   return ret.retn();
8066 }
8067
8068 /*!
8069  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8070  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8071  */
8072 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8073 {
8074   double *w=zipFrmt;
8075   if(spaceDim==3)
8076     for(int i=0;i<nbOfNodesInCell;i++)
8077       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8078   else if(spaceDim==2)
8079     {
8080       for(int i=0;i<nbOfNodesInCell;i++)
8081         {
8082           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8083           *w++=0.;
8084         }
8085     }
8086   else
8087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8088 }
8089
8090 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8091 {
8092   int nbOfCells=getNumberOfCells();
8093   if(nbOfCells<=0)
8094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8095   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};
8096   ofs << "  <" << getVTKDataSetType() << ">\n";
8097   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8098   ofs << "      <PointData>\n" << pointData << std::endl;
8099   ofs << "      </PointData>\n";
8100   ofs << "      <CellData>\n" << cellData << std::endl;
8101   ofs << "      </CellData>\n";
8102   ofs << "      <Points>\n";
8103   if(getSpaceDimension()==3)
8104     _coords->writeVTK(ofs,8,"Points",byteData);
8105   else
8106     {
8107       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8108       coo->writeVTK(ofs,8,"Points",byteData);
8109     }
8110   ofs << "      </Points>\n";
8111   ofs << "      <Cells>\n";
8112   const int *cPtr=_nodal_connec->getConstPointer();
8113   const int *cIPtr=_nodal_connec_index->getConstPointer();
8114   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8115   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8116   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8117   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8118   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8119   int szFaceOffsets=0,szConn=0;
8120   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8121     {
8122       *w2=cPtr[cIPtr[i]];
8123       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8124         {
8125           *w1=-1;
8126           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8127           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8128         }
8129       else
8130         {
8131           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8132           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8133           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8134           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8135           w4=std::copy(c.begin(),c.end(),w4);
8136         }
8137     }
8138   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8139   types->writeVTK(ofs,8,"UInt8","types",byteData);
8140   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8141   if(szFaceOffsets!=0)
8142     {//presence of Polyhedra
8143       connectivity->reAlloc(szConn);
8144       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8145       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8146       w1=faces->getPointer();
8147       for(int i=0;i<nbOfCells;i++)
8148         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8149           {
8150             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8151             *w1++=nbFaces;
8152             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8153             for(int j=0;j<nbFaces;j++)
8154               {
8155                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8156                 *w1++=(int)std::distance(w6,w5);
8157                 w1=std::copy(w6,w5,w1);
8158                 w6=w5+1;
8159               }
8160           }
8161       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8162     }
8163   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8164   ofs << "      </Cells>\n";
8165   ofs << "    </Piece>\n";
8166   ofs << "  </" << getVTKDataSetType() << ">\n";
8167 }
8168
8169 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8170 {
8171   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8172   if(_mesh_dim==-2)
8173     { stream << " Not set !"; return ; }
8174   stream << " Mesh dimension : " << _mesh_dim << ".";
8175   if(_mesh_dim==-1)
8176     return ;
8177   if(!_coords)
8178     { stream << " No coordinates set !"; return ; }
8179   if(!_coords->isAllocated())
8180     { stream << " Coordinates set but not allocated !"; return ; }
8181   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8182   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8183   if(!_nodal_connec_index)
8184     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8185   if(!_nodal_connec_index->isAllocated())
8186     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8187   int lgth=_nodal_connec_index->getNumberOfTuples();
8188   int cpt=_nodal_connec_index->getNumberOfComponents();
8189   if(cpt!=1 || lgth<1)
8190     return ;
8191   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8192 }
8193
8194 std::string MEDCouplingUMesh::getVTKDataSetType() const
8195 {
8196   return std::string("UnstructuredGrid");
8197 }
8198
8199 /*!
8200  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8201  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8202  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8203  * meshes.
8204  *  \param [in] m1 - the first input mesh which is a partitioned object.
8205  *  \param [in] m2 - the second input mesh which is a partition tool.
8206  *  \param [in] eps - precision used to detect coincident mesh entities.
8207  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8208  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8209  *         this array using decrRef() as it is no more needed.
8210  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8211  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8212  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8213  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8214  *         it is no more needed.  
8215  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8216  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8217  *         is no more needed.  
8218  *  \throw If the coordinates array is not set in any of the meshes.
8219  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8220  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8221  */
8222 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8223 {
8224   m1->checkFullyDefined();
8225   m2->checkFullyDefined();
8226   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8227     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8228   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8229   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8230   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8231   std::vector<double> addCoo,addCoordsQuadratic;
8232   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8233   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8234   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8235                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8236   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8238   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8239   std::vector< std::vector<int> > intersectEdge2;
8240   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8241   subDiv2.clear(); dd5=0; dd6=0;
8242   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8243   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8244   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8245                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8246   //
8247   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8248   addCooDa->alloc((int)(addCoo.size())/2,2);
8249   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8250   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8251   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8252   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8253   std::vector<const DataArrayDouble *> coordss(4);
8254   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8255   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8256   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8257   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8258   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8260   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8261   ret->setConnectivity(conn,connI,true);
8262   ret->setCoords(coo);
8263   cellNb1=c1.retn(); cellNb2=c2.retn();
8264   return ret.retn();
8265 }
8266
8267 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8268                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8269                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8270                                                          const std::vector<double>& addCoords,
8271                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8272 {
8273   static const int SPACEDIM=2;
8274   const double *coo1=m1->getCoords()->getConstPointer();
8275   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8276   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8277   int offset1=m1->getNumberOfNodes();
8278   const double *coo2=m2->getCoords()->getConstPointer();
8279   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8280   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8281   int offset2=offset1+m2->getNumberOfNodes();
8282   int offset3=offset2+((int)addCoords.size())/2;
8283   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8284   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8285   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8286   int ncell1=m1->getNumberOfCells();
8287   crI.push_back(0);
8288   for(int i=0;i<ncell1;i++)
8289     {
8290       std::vector<int> candidates2;
8291       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8292       std::map<INTERP_KERNEL::Node *,int> mapp;
8293       std::map<int,INTERP_KERNEL::Node *> mappRev;
8294       INTERP_KERNEL::QuadraticPolygon pol1;
8295       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8296       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8297       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8298       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8299                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8300       //
8301       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
8302       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8303       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8304       for(it1.first();!it1.finished();it1.next())
8305         edges1.insert(it1.current()->getPtr());
8306       //
8307       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8308       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8309       int ii=0;
8310       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8311         {
8312           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8313           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8314           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8315           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8316                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8317         }
8318       ii=0;
8319       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8320         {
8321           pol1.initLocationsWithOther(pol2s[ii]);
8322           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8323           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8324           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8325         }
8326       if(!edges1.empty())
8327         {
8328           try
8329             {
8330               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8331             }
8332           catch(INTERP_KERNEL::Exception& e)
8333             {
8334               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();
8335               throw INTERP_KERNEL::Exception(oss.str().c_str());
8336             }
8337         }
8338       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8339         (*it).second->decrRef();
8340     }
8341 }
8342
8343 /*!
8344  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8345  * 
8346  */
8347 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8348                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8349                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8350                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8351                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8352 {
8353   static const int SPACEDIM=2;
8354   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8355   desc2=DataArrayInt::New();
8356   descIndx2=DataArrayInt::New();
8357   revDesc2=DataArrayInt::New();
8358   revDescIndx2=DataArrayInt::New();
8359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8361   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8362   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8363   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8364   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8365   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8366   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8367   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8368   int ncell1=m1Desc->getNumberOfCells();
8369   int ncell2=m2Desc->getNumberOfCells();
8370   intersectEdge1.resize(ncell1);
8371   colinear2.resize(ncell2);
8372   subDiv2.resize(ncell2);
8373   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8374   std::vector<int> candidates1(1);
8375   int offset1=m1->getNumberOfNodes();
8376   int offset2=offset1+m2->getNumberOfNodes();
8377   for(int i=0;i<ncell1;i++)
8378     {
8379       std::vector<int> candidates2;
8380       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8381       if(!candidates2.empty())
8382         {
8383           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8384           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8385           candidates1[0]=i;
8386           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8387           // this following part is to avoid that a some remove nodes (for example due to a merge between pol1 and pol2) can be replaced by a newlt created one
8388           // This trick garanties that Node * are discriminant
8389           std::set<INTERP_KERNEL::Node *> nodes;
8390           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
8391           std::size_t szz(nodes.size());
8392           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
8393           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
8394           for(std::size_t iii=0;iii<szz;iii++,itt++)
8395             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
8396           // end of protection
8397           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8398           delete pol2;
8399           delete pol1;
8400         }
8401       else
8402         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8403     }
8404   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8405   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8406 }
8407
8408 /*!
8409  * This method performs the 2nd step of Partition of 2D mesh.
8410  * This method has 4 inputs :
8411  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8412  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8413  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8414  * 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'
8415  * \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'
8416  * \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.
8417  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8418  */
8419 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)
8420 {
8421   int offset1=m1->getNumberOfNodes();
8422   int ncell=m2->getNumberOfCells();
8423   const int *c=m2->getNodalConnectivity()->getConstPointer();
8424   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8425   const double *coo=m2->getCoords()->getConstPointer();
8426   const double *cooBis=m1->getCoords()->getConstPointer();
8427   int offset2=offset1+m2->getNumberOfNodes();
8428   intersectEdge.resize(ncell);
8429   for(int i=0;i<ncell;i++,cI++)
8430     {
8431       const std::vector<int>& divs=subDiv[i];
8432       int nnode=cI[1]-cI[0]-1;
8433       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8434       std::map<INTERP_KERNEL::Node *, int> mapp22;
8435       for(int j=0;j<nnode;j++)
8436         {
8437           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8438           int nnid=c[(*cI)+j+1];
8439           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8440           mapp22[nn]=nnid+offset1;
8441         }
8442       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8443       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8444         ((*it).second.first)->decrRef();
8445       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8446       std::map<INTERP_KERNEL::Node *,int> mapp3;
8447       for(std::size_t j=0;j<divs.size();j++)
8448         {
8449           int id=divs[j];
8450           INTERP_KERNEL::Node *tmp=0;
8451           if(id<offset1)
8452             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8453           else if(id<offset2)
8454             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8455           else
8456             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8457           addNodes[j]=tmp;
8458           mapp3[tmp]=id;
8459         }
8460       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8461       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8462         (*it)->decrRef();
8463       e->decrRef();
8464     }
8465 }
8466
8467 /*!
8468  * 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).
8469  * 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
8470  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8471  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8472  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8473  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8474  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8475  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8476  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8477  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8478  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8479  * \param [out] cut3DSuf input/output param.
8480  */
8481 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8482                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8483                                                    const int *desc, const int *descIndx, 
8484                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8485 {
8486   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8487   int nbOf3DSurfCell=(int)cut3DSurf.size();
8488   for(int i=0;i<nbOf3DSurfCell;i++)
8489     {
8490       std::vector<int> res;
8491       int offset=descIndx[i];
8492       int nbOfSeg=descIndx[i+1]-offset;
8493       for(int j=0;j<nbOfSeg;j++)
8494         {
8495           int edgeId=desc[offset+j];
8496           int status=cut3DCurve[edgeId];
8497           if(status!=-2)
8498             {
8499               if(status>-1)
8500                 res.push_back(status);
8501               else
8502                 {
8503                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8504                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8505                 }
8506             }
8507         }
8508       switch(res.size())
8509         {
8510         case 2:
8511           {
8512             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8513             break;
8514           }
8515         case 1:
8516         case 0:
8517           {
8518             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8519             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8520             if(res.size()==2)
8521               {
8522                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8523               }
8524             else
8525               {
8526                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8527               }
8528             break;
8529           }
8530         default:
8531           {// case when plane is on a multi colinear edge of a polyhedron
8532             if((int)res.size()==2*nbOfSeg)
8533               {
8534                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8535               }
8536             else
8537               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8538           }
8539         }
8540     }
8541 }
8542
8543 /*!
8544  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8545  * 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).
8546  * 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
8547  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8548  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8549  * \param desc is the descending connectivity 3D->3DSurf
8550  * \param descIndx is the descending connectivity index 3D->3DSurf
8551  */
8552 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8553                                                   const int *desc, const int *descIndx,
8554                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8555 {
8556   checkFullyDefined();
8557   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8558     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8559   const int *nodal3D=_nodal_connec->getConstPointer();
8560   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8561   int nbOfCells=getNumberOfCells();
8562   for(int i=0;i<nbOfCells;i++)
8563     {
8564       std::map<int, std::set<int> > m;
8565       int offset=descIndx[i];
8566       int nbOfFaces=descIndx[i+1]-offset;
8567       int start=-1;
8568       int end=-1;
8569       for(int j=0;j<nbOfFaces;j++)
8570         {
8571           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8572           if(p.first!=-1 && p.second!=-1)
8573             {
8574               if(p.first!=-2)
8575                 {
8576                   start=p.first; end=p.second;
8577                   m[p.first].insert(p.second);
8578                   m[p.second].insert(p.first);
8579                 }
8580               else
8581                 {
8582                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8583                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8584                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8585                   INTERP_KERNEL::NormalizedCellType cmsId;
8586                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8587                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8588                   for(unsigned k=0;k<nbOfNodesSon;k++)
8589                     {
8590                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8591                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8592                     }
8593                 }
8594             }
8595         }
8596       if(m.empty())
8597         continue;
8598       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8599       int prev=end;
8600       while(end!=start)
8601         {
8602           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8603           const std::set<int>& s=(*it).second;
8604           std::set<int> s2; s2.insert(prev);
8605           std::set<int> s3;
8606           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8607           if(s3.size()==1)
8608             {
8609               int val=*s3.begin();
8610               conn.push_back(start);
8611               prev=start;
8612               start=val;
8613             }
8614           else
8615             start=end;
8616         }
8617       conn.push_back(end);
8618       if(conn.size()>3)
8619         {
8620           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8621           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8622           cellIds->pushBackSilent(i);
8623         }
8624     }
8625 }
8626
8627 /*!
8628  * 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
8629  * 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
8630  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8631  * 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
8632  * 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.
8633  * 
8634  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8635  */
8636 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
8637 {
8638   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8639   if(sz>=4)
8640     {
8641       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8642       if(cm.getDimension()==2)
8643         {
8644           const int *node=nodalConnBg+1;
8645           int startNode=*node++;
8646           double refX=coords[2*startNode];
8647           for(;node!=nodalConnEnd;node++)
8648             {
8649               if(coords[2*(*node)]<refX)
8650                 {
8651                   startNode=*node;
8652                   refX=coords[2*startNode];
8653                 }
8654             }
8655           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8656           refX=1e300;
8657           double tmp1;
8658           double tmp2[2];
8659           double angle0=-M_PI/2;
8660           //
8661           int nextNode=-1;
8662           int prevNode=-1;
8663           double resRef;
8664           double angleNext=0.;
8665           while(nextNode!=startNode)
8666             {
8667               nextNode=-1;
8668               resRef=1e300;
8669               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8670                 {
8671                   if(*node!=tmpOut.back() && *node!=prevNode)
8672                     {
8673                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8674                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8675                       double res;
8676                       if(angleM<=angle0)
8677                         res=angle0-angleM;
8678                       else
8679                         res=angle0-angleM+2.*M_PI;
8680                       if(res<resRef)
8681                         {
8682                           nextNode=*node;
8683                           resRef=res;
8684                           angleNext=angleM;
8685                         }
8686                     }
8687                 }
8688               if(nextNode!=startNode)
8689                 {
8690                   angle0=angleNext-M_PI;
8691                   if(angle0<-M_PI)
8692                     angle0+=2*M_PI;
8693                   prevNode=tmpOut.back();
8694                   tmpOut.push_back(nextNode);
8695                 }
8696             }
8697           std::vector<int> tmp3(2*(sz-1));
8698           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8699           std::copy(nodalConnBg+1,nodalConnEnd,it);
8700           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8701             {
8702               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8703               return false;
8704             }
8705           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8706             {
8707               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8708               return false;
8709             }
8710           else
8711             {
8712               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8713               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8714               return true;
8715             }
8716         }
8717       else
8718         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8719     }
8720   else
8721     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8722 }
8723
8724 /*!
8725  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8726  * 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.
8727  * 
8728  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8729  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8730  * \param [in,out] arr array in which the remove operation will be done.
8731  * \param [in,out] arrIndx array in the remove operation will modify
8732  * \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])
8733  * \return true if \b arr and \b arrIndx have been modified, false if not.
8734  */
8735 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
8736 {
8737   if(!arrIndx || !arr)
8738     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8739   if(offsetForRemoval<0)
8740     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8741   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8742   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8743   int *arrIPtr=arrIndx->getPointer();
8744   *arrIPtr++=0;
8745   int previousArrI=0;
8746   const int *arrPtr=arr->getConstPointer();
8747   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8748   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8749     {
8750       if(*arrIPtr-previousArrI>offsetForRemoval)
8751         {
8752           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8753             {
8754               if(s.find(*work)==s.end())
8755                 arrOut.push_back(*work);
8756             }
8757         }
8758       previousArrI=*arrIPtr;
8759       *arrIPtr=(int)arrOut.size();
8760     }
8761   if(arr->getNumberOfTuples()==(int)arrOut.size())
8762     return false;
8763   arr->alloc((int)arrOut.size(),1);
8764   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8765   return true;
8766 }
8767
8768 /*!
8769  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8770  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8771  * The selection of extraction is done standardly in new2old format.
8772  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8773  *
8774  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8775  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8776  * \param [in] arrIn arr origin array from which the extraction will be done.
8777  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8778  * \param [out] arrOut the resulting array
8779  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8780  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8781  */
8782 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8783                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8784 {
8785   if(!arrIn || !arrIndxIn)
8786     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8787   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8788   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8789     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8790   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8791   const int *arrInPtr=arrIn->getConstPointer();
8792   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8793   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8794   if(nbOfGrps<0)
8795     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8796   int maxSizeOfArr=arrIn->getNumberOfTuples();
8797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8798   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8799   arrIo->alloc((int)(sz+1),1);
8800   const int *idsIt=idsOfSelectBg;
8801   int *work=arrIo->getPointer();
8802   *work++=0;
8803   int lgth=0;
8804   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8805     {
8806       if(*idsIt>=0 && *idsIt<nbOfGrps)
8807         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8808       else
8809         {
8810           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8811           throw INTERP_KERNEL::Exception(oss.str().c_str());
8812         }
8813       if(lgth>=work[-1])
8814         *work=lgth;
8815       else
8816         {
8817           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8818           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8819           throw INTERP_KERNEL::Exception(oss.str().c_str());
8820         }
8821     }
8822   arro->alloc(lgth,1);
8823   work=arro->getPointer();
8824   idsIt=idsOfSelectBg;
8825   for(std::size_t i=0;i<sz;i++,idsIt++)
8826     {
8827       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8828         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8829       else
8830         {
8831           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8832           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8833           throw INTERP_KERNEL::Exception(oss.str().c_str());
8834         }
8835     }
8836   arrOut=arro.retn();
8837   arrIndexOut=arrIo.retn();
8838 }
8839
8840 /*!
8841  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8842  * 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 ).
8843  * The selection of extraction is done standardly in new2old format.
8844  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8845  *
8846  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8847  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8848  * \param [in] arrIn arr origin array from which the extraction will be done.
8849  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8850  * \param [out] arrOut the resulting array
8851  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8852  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8853  */
8854 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8855                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8856 {
8857   if(!arrIn || !arrIndxIn)
8858     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8859   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8860   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8861     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8862   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8863   const int *arrInPtr=arrIn->getConstPointer();
8864   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8865   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8866   if(nbOfGrps<0)
8867     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8868   int maxSizeOfArr=arrIn->getNumberOfTuples();
8869   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8870   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8871   arrIo->alloc((int)(sz+1),1);
8872   int idsIt=idsOfSelectStart;
8873   int *work=arrIo->getPointer();
8874   *work++=0;
8875   int lgth=0;
8876   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8877     {
8878       if(idsIt>=0 && idsIt<nbOfGrps)
8879         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8880       else
8881         {
8882           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8883           throw INTERP_KERNEL::Exception(oss.str().c_str());
8884         }
8885       if(lgth>=work[-1])
8886         *work=lgth;
8887       else
8888         {
8889           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8890           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8891           throw INTERP_KERNEL::Exception(oss.str().c_str());
8892         }
8893     }
8894   arro->alloc(lgth,1);
8895   work=arro->getPointer();
8896   idsIt=idsOfSelectStart;
8897   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8898     {
8899       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8900         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8901       else
8902         {
8903           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8904           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8905           throw INTERP_KERNEL::Exception(oss.str().c_str());
8906         }
8907     }
8908   arrOut=arro.retn();
8909   arrIndexOut=arrIo.retn();
8910 }
8911
8912 /*!
8913  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8914  * 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
8915  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8916  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8917  *
8918  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8919  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8920  * \param [in] arrIn arr origin array from which the extraction will be done.
8921  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8922  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8923  * \param [in] srcArrIndex index array of \b srcArr
8924  * \param [out] arrOut the resulting array
8925  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8926  * 
8927  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8928  */
8929 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8930                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8931                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8932 {
8933   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8934     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8935   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8936   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8937   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8938   std::vector<bool> v(nbOfTuples,true);
8939   int offset=0;
8940   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8941   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8942   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8943     {
8944       if(*it>=0 && *it<nbOfTuples)
8945         {
8946           v[*it]=false;
8947           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8948         }
8949       else
8950         {
8951           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8952           throw INTERP_KERNEL::Exception(oss.str().c_str());
8953         }
8954     }
8955   srcArrIndexPtr=srcArrIndex->getConstPointer();
8956   arrIo->alloc(nbOfTuples+1,1);
8957   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8958   const int *arrInPtr=arrIn->getConstPointer();
8959   const int *srcArrPtr=srcArr->getConstPointer();
8960   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8961   int *arroPtr=arro->getPointer();
8962   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8963     {
8964       if(v[ii])
8965         {
8966           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8967           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8968         }
8969       else
8970         {
8971           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8972           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8973           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8974         }
8975     }
8976   arrOut=arro.retn();
8977   arrIndexOut=arrIo.retn();
8978 }
8979
8980 /*!
8981  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8982  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8983  *
8984  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8985  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8986  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8987  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8988  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8989  * \param [in] srcArrIndex index array of \b srcArr
8990  * 
8991  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8992  */
8993 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8994                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8995 {
8996   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8997     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8998   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8999   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9000   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9001   int *arrInOutPtr=arrInOut->getPointer();
9002   const int *srcArrPtr=srcArr->getConstPointer();
9003   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9004     {
9005       if(*it>=0 && *it<nbOfTuples)
9006         {
9007           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9008             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9009           else
9010             {
9011               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] !";
9012               throw INTERP_KERNEL::Exception(oss.str().c_str());
9013             }
9014         }
9015       else
9016         {
9017           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9018           throw INTERP_KERNEL::Exception(oss.str().c_str());
9019         }
9020     }
9021 }
9022
9023 /*!
9024  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9025  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9026  * 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]].
9027  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9028  * A negative value in \b arrIn means that it is ignored.
9029  * 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.
9030  * 
9031  * \param [in] arrIn arr origin array from which the extraction will be done.
9032  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9033  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9034  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9035  */
9036 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9037 {
9038   int seed=0,nbOfDepthPeelingPerformed=0;
9039   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9040 }
9041
9042 /*!
9043  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9044  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9045  * 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]].
9046  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9047  * A negative value in \b arrIn means that it is ignored.
9048  * 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.
9049  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9050  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9051  * \param [in] arrIn arr origin array from which the extraction will be done.
9052  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9053  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9054  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9055  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9056  * \sa MEDCouplingUMesh::partitionBySpreadZone
9057  */
9058 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9059 {
9060   nbOfDepthPeelingPerformed=0;
9061   if(!arrIndxIn)
9062     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9063   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9064   if(nbOfTuples<=0)
9065     {
9066       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9067       return ret;
9068     }
9069   //
9070   std::vector<bool> fetched(nbOfTuples,false);
9071   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9072 }
9073
9074 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9075 {
9076   nbOfDepthPeelingPerformed=0;
9077   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9078     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9079   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9080   std::vector<bool> fetched2(nbOfTuples,false);
9081   int i=0;
9082   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9083     {
9084       if(*seedElt>=0 && *seedElt<nbOfTuples)
9085         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9086       else
9087         { 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()); }
9088     }
9089   const int *arrInPtr=arrIn->getConstPointer();
9090   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9091   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9092   std::vector<int> idsToFetch1(seedBg,seedEnd);
9093   std::vector<int> idsToFetch2;
9094   std::vector<int> *idsToFetch=&idsToFetch1;
9095   std::vector<int> *idsToFetchOther=&idsToFetch2;
9096   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9097     {
9098       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9099         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9100           if(!fetched[*it2])
9101             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9102       std::swap(idsToFetch,idsToFetchOther);
9103       idsToFetchOther->clear();
9104       nbOfDepthPeelingPerformed++;
9105     }
9106   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9107   i=0;
9108   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9109   int *retPtr=ret->getPointer();
9110   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9111     if(*it)
9112       *retPtr++=i;
9113   return ret.retn();
9114 }
9115
9116 /*!
9117  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9118  * 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
9119  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9120  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9121  *
9122  * \param [in] start begin of set of ids of the input extraction (included)
9123  * \param [in] end end of set of ids of the input extraction (excluded)
9124  * \param [in] step step of the set of ids in range mode.
9125  * \param [in] arrIn arr origin array from which the extraction will be done.
9126  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9127  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9128  * \param [in] srcArrIndex index array of \b srcArr
9129  * \param [out] arrOut the resulting array
9130  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9131  * 
9132  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9133  */
9134 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9135                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9136                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9137 {
9138   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9139     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9140   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9141   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9142   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9143   int offset=0;
9144   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9145   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9146   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9147   int it=start;
9148   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9149     {
9150       if(it>=0 && it<nbOfTuples)
9151         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9152       else
9153         {
9154           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9155           throw INTERP_KERNEL::Exception(oss.str().c_str());
9156         }
9157     }
9158   srcArrIndexPtr=srcArrIndex->getConstPointer();
9159   arrIo->alloc(nbOfTuples+1,1);
9160   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9161   const int *arrInPtr=arrIn->getConstPointer();
9162   const int *srcArrPtr=srcArr->getConstPointer();
9163   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9164   int *arroPtr=arro->getPointer();
9165   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9166     {
9167       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9168       if(pos<0)
9169         {
9170           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9171           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9172         }
9173       else
9174         {
9175           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9176           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9177         }
9178     }
9179   arrOut=arro.retn();
9180   arrIndexOut=arrIo.retn();
9181 }
9182
9183 /*!
9184  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9185  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9186  *
9187  * \param [in] start begin of set of ids of the input extraction (included)
9188  * \param [in] end end of set of ids of the input extraction (excluded)
9189  * \param [in] step step of the set of ids in range mode.
9190  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9191  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9192  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9193  * \param [in] srcArrIndex index array of \b srcArr
9194  * 
9195  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9196  */
9197 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9198                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9199 {
9200   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9201     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9202   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9203   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9204   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9205   int *arrInOutPtr=arrInOut->getPointer();
9206   const int *srcArrPtr=srcArr->getConstPointer();
9207   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9208   int it=start;
9209   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9210     {
9211       if(it>=0 && it<nbOfTuples)
9212         {
9213           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9214             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9215           else
9216             {
9217               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9218               throw INTERP_KERNEL::Exception(oss.str().c_str());
9219             }
9220         }
9221       else
9222         {
9223           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9224           throw INTERP_KERNEL::Exception(oss.str().c_str());
9225         }
9226     }
9227 }
9228
9229 /*!
9230  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9231  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9232  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9233  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9234  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9235  * 
9236  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9237  */
9238 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9239 {
9240   checkFullyDefined();
9241   int mdim=getMeshDimension();
9242   int spaceDim=getSpaceDimension();
9243   if(mdim!=spaceDim)
9244     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9245   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9246   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9247   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9248   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9249   ret->setCoords(getCoords());
9250   ret->allocateCells((int)partition.size());
9251   //
9252   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9253     {
9254       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9255       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9256       switch(mdim)
9257         {
9258         case 2:
9259           cell=tmp->buildUnionOf2DMesh();
9260           break;
9261         case 3:
9262           cell=tmp->buildUnionOf3DMesh();
9263           break;
9264         default:
9265           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9266         }
9267       
9268       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9269     }
9270   //
9271   ret->finishInsertingCells();
9272   return ret.retn();
9273 }
9274
9275 /*!
9276  * This method partitions \b this into contiguous zone.
9277  * This method only needs a well defined connectivity. Coordinates are not considered here.
9278  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9279  */
9280 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9281 {
9282   int nbOfCellsCur=getNumberOfCells();
9283   std::vector<DataArrayInt *> ret;
9284   if(nbOfCellsCur<=0)
9285     return ret;
9286   DataArrayInt *neigh=0,*neighI=0;
9287   computeNeighborsOfCells(neigh,neighI);
9288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9289   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9290   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9291   int seed=0;
9292   while(seed<nbOfCellsCur)
9293     {
9294       int nbOfPeelPerformed=0;
9295       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9296       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9297     }
9298   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9299     ret.push_back((*it).retn());
9300   return ret;
9301 }
9302
9303 /*!
9304  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9305  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9306  *
9307  * \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.
9308  * \return a newly allocated DataArrayInt to be managed by the caller.
9309  * \throw In case of \a code has not the right format (typically of size 3*n)
9310  */
9311 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9312 {
9313   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9314   std::size_t nb=code.size()/3;
9315   if(code.size()%3!=0)
9316     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9317   ret->alloc((int)nb,2);
9318   int *retPtr=ret->getPointer();
9319   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9320     {
9321       retPtr[0]=code[3*i+2];
9322       retPtr[1]=code[3*i+2]+code[3*i+1];
9323     }
9324   return ret.retn();
9325 }
9326
9327 /*!
9328  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9329  * All cells in \a this are expected to be linear 3D cells.
9330  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9331  * It leads to an increase to number of cells.
9332  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9333  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
9334  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9335  *
9336  * \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.
9337  *                      For all other cells, the splitting policy will be ignored.
9338  * \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. 
9339  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9340  *          an id of old cell producing it. The caller is to delete this array using
9341  *         decrRef() as it is no more needed.
9342  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9343  * 
9344  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9345  * \throw If \a this is not fully constituted with linear 3D cells.
9346  * \sa MEDCouplingUMesh::simplexize
9347  */
9348 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
9349 {
9350   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9351   checkConnectivityFullyDefined();
9352   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9354   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9355   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
9356   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9357   int *retPt(ret->getPointer());
9358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9359   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9360   const int *oldc(_nodal_connec->begin());
9361   const int *oldci(_nodal_connec_index->begin());
9362   const double *coords(_coords->begin());
9363   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9364     {
9365       std::vector<int> a; std::vector<double> b;
9366       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9367       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9368       const int *aa(&a[0]);
9369       if(!b.empty())
9370         {
9371           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9372             if(*it<0)
9373               *it=(-(*(it))-1+nbNodes);
9374           addPts->insertAtTheEnd(b.begin(),b.end());
9375           nbNodes+=(int)b.size()/3;
9376         }
9377       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9378         newConn->insertAtTheEnd(aa,aa+4);
9379     }
9380   if(!addPts->empty())
9381     {
9382       addPts->rearrange(3);
9383       nbOfAdditionalPoints=addPts->getNumberOfTuples();
9384       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9385       ret0->setCoords(addPts);
9386     }
9387   else
9388     {
9389       nbOfAdditionalPoints=0;
9390       ret0->setCoords(getCoords());
9391     }
9392   ret0->setNodalConnectivity(newConn);
9393   //
9394   ret->computeOffsets2();
9395   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9396   return ret0.retn();
9397 }
9398
9399 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9400                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9401 {
9402   if(mesh)
9403     {
9404       mesh->incrRef();
9405       _nb_cell=mesh->getNumberOfCells();
9406     }
9407 }
9408
9409 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9410 {
9411   if(_mesh)
9412     _mesh->decrRef();
9413   if(_own_cell)
9414     delete _cell;
9415 }
9416
9417 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9418                                                                                                                                _own_cell(false),_cell_id(bg-1),
9419                                                                                                                                _nb_cell(end)
9420 {
9421   if(mesh)
9422     mesh->incrRef();
9423 }
9424
9425 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9426 {
9427   _cell_id++;
9428   if(_cell_id<_nb_cell)
9429     {
9430       _cell->next();
9431       return _cell;
9432     }
9433   else
9434     return 0;
9435 }
9436
9437 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9438 {
9439   if(_mesh)
9440     _mesh->incrRef();
9441 }
9442
9443 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9444 {
9445   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9446 }
9447
9448 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9449 {
9450   if(_mesh)
9451     _mesh->decrRef();
9452 }
9453
9454 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9455                                                                                                                                                                   _itc(itc),
9456                                                                                                                                                                   _bg(bg),_end(end)
9457 {
9458   if(_mesh)
9459     _mesh->incrRef();
9460 }
9461
9462 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9463 {
9464   if(_mesh)
9465     _mesh->decrRef();
9466 }
9467
9468 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9469 {
9470   return _type;
9471 }
9472
9473 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9474 {
9475   return _end-_bg;
9476 }
9477
9478 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9479 {
9480   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9481 }
9482
9483 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9484 {
9485   if(mesh)
9486     {
9487       mesh->incrRef();
9488       _nb_cell=mesh->getNumberOfCells();
9489     }
9490 }
9491
9492 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9493 {
9494   if(_mesh)
9495     _mesh->decrRef();
9496   delete _cell;
9497 }
9498
9499 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9500 {
9501   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9502   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9503   if(_cell_id<_nb_cell)
9504     {
9505       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9506       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9507       int startId=_cell_id;
9508       _cell_id+=nbOfElems;
9509       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9510     }
9511   else
9512     return 0;
9513 }
9514
9515 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9516 {
9517   if(mesh)
9518     {
9519       _conn=mesh->getNodalConnectivity()->getPointer();
9520       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9521     }
9522 }
9523
9524 void MEDCouplingUMeshCell::next()
9525 {
9526   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9527     {
9528       _conn+=_conn_lgth;
9529       _conn_indx++;
9530     }
9531   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9532 }
9533
9534 std::string MEDCouplingUMeshCell::repr() const
9535 {
9536   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9537     {
9538       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9539       oss << " : ";
9540       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9541       return oss.str();
9542     }
9543   else
9544     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9545 }
9546
9547 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9548 {
9549   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9550     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9551   else
9552     return INTERP_KERNEL::NORM_ERROR;
9553 }
9554
9555 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9556 {
9557   lgth=_conn_lgth;
9558   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9559     return _conn;
9560   else
9561     return 0;
9562 }