]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/MEDCoupling/MEDCouplingUMesh.cxx
Salome HOME
05bd3c7a7dc6a96a65c57ebeb2d9f27bf4d9b0b0
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildren() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
128   if(_nodal_connec)
129     ret.push_back(_nodal_connec);
130   if(_nodal_connec_index)
131     ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
247         {
248           int nodeId=*w;
249           if(nodeId>=0)
250             {
251               if(nodeId>=nbOfNodes)
252                 {
253                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254                   throw INTERP_KERNEL::Exception(oss.str().c_str());
255                 }
256             }
257           else if(nodeId<-1)
258             {
259               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260               throw INTERP_KERNEL::Exception(oss.str().c_str());
261             }
262           else
263             {
264               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
265                 {
266                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267                   throw INTERP_KERNEL::Exception(oss.str().c_str());
268                 }
269             }
270         }
271     }
272 }
273
274
275 /*!
276  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277  * then \a this mesh is most probably is writable, exchangeable and available for all
278  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
279  *  \param [in] eps - a not used parameter.
280  *  \throw If the mesh dimension is not set.
281  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
282  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283  *  \throw If the connectivity data array has more than one component.
284  *  \throw If the connectivity data array has a named component.
285  *  \throw If the connectivity index data array has more than one component.
286  *  \throw If the connectivity index data array has a named component.
287  *  \throw If number of nodes defining an element does not correspond to the type of element.
288  *  \throw If the nodal connectivity includes an invalid node id.
289  */
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
291 {
292   checkCoherency1(eps);
293 }
294
295 /*!
296  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297  * elements contained in the mesh. For more info on the mesh dimension see
298  * \ref MEDCouplingUMeshPage.
299  *  \param [in] meshDim - a new mesh dimension.
300  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
301  */
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
303 {
304   if(meshDim<-1 || meshDim>3)
305     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
306   _mesh_dim=meshDim;
307   declareAsNew();
308 }
309
310 /*!
311  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
314  *
315  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
316  *
317  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
318  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
319  */
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
321 {
322   if(nbOfCells<0)
323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324   if(_nodal_connec_index)
325     {
326       _nodal_connec_index->decrRef();
327     }
328   if(_nodal_connec)
329     {
330       _nodal_connec->decrRef();
331     }
332   _nodal_connec_index=DataArrayInt::New();
333   _nodal_connec_index->reserve(nbOfCells+1);
334   _nodal_connec_index->pushBackSilent(0);
335   _nodal_connec=DataArrayInt::New();
336   _nodal_connec->reserve(2*nbOfCells);
337   _types.clear();
338   declareAsNew();
339 }
340
341 /*!
342  * Appends a cell to the connectivity array. For deeper understanding what is
343  * happening see \ref MEDCouplingUMeshNodalConnectivity.
344  *  \param [in] type - type of cell to add.
345  *  \param [in] size - number of nodes constituting this cell.
346  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
347  * 
348  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
349  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
350  */
351 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
352 {
353   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
354   if(_nodal_connec_index==0)
355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
356   if((int)cm.getDimension()==_mesh_dim)
357     {
358       if(!cm.isDynamic())
359         if(size!=(int)cm.getNumberOfNodes())
360           {
361             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
362             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
363             throw INTERP_KERNEL::Exception(oss.str().c_str());
364           }
365       int idx=_nodal_connec_index->back();
366       int val=idx+size+1;
367       _nodal_connec_index->pushBackSilent(val);
368       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
369       _types.insert(type);
370     }
371   else
372     {
373       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
374       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
375       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
376       throw INTERP_KERNEL::Exception(oss.str().c_str());
377     }
378 }
379
380 /*!
381  * Compacts data arrays to release unused memory. This method is to be called after
382  * finishing cell insertion using \a this->insertNextCell().
383  * 
384  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
385  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
386  */
387 void MEDCouplingUMesh::finishInsertingCells()
388 {
389   _nodal_connec->pack();
390   _nodal_connec_index->pack();
391   _nodal_connec->declareAsNew();
392   _nodal_connec_index->declareAsNew();
393   updateTime();
394 }
395
396 /*!
397  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
398  * Useful for python users.
399  */
400 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
401 {
402   return new MEDCouplingUMeshCellIterator(this);
403 }
404
405 /*!
406  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
407  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
408  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
409  * Useful for python users.
410  */
411 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
412 {
413   if(!checkConsecutiveCellTypes())
414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
415   return new MEDCouplingUMeshCellByTypeEntry(this);
416 }
417
418 /*!
419  * Returns a set of all cell types available in \a this mesh.
420  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
421  * \warning this method does not throw any exception even if \a this is not defined.
422  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
423  */
424 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
425 {
426   return _types;
427 }
428
429 /*!
430  * This method returns the sorted list of geometric types in \a this.
431  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
432  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
433  *
434  * \throw if connectivity in \a this is not correctly defined.
435  *  
436  * \sa MEDCouplingMesh::getAllGeoTypes
437  */
438 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
439 {
440   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
441   checkConnectivityFullyDefined();
442   int nbOfCells(getNumberOfCells());
443   if(nbOfCells==0)
444     return ret;
445   if(getMeshLength()<1)
446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
447   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
448   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
449   for(int i=1;i<nbOfCells;i++,ci++)
450     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
451       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
452   return ret;
453 }
454
455 /*!
456  * This method is a method that compares \a this and \a other.
457  * This method compares \b all attributes, even names and component names.
458  */
459 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
460 {
461   if(!other)
462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
463   std::ostringstream oss; oss.precision(15);
464   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
465   if(!otherC)
466     {
467       reason="mesh given in input is not castable in MEDCouplingUMesh !";
468       return false;
469     }
470   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
471     return false;
472   if(_mesh_dim!=otherC->_mesh_dim)
473     {
474       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
475       reason=oss.str();
476       return false;
477     }
478   if(_types!=otherC->_types)
479     {
480       oss << "umesh geometric type mismatch :\nThis geometric types are :";
481       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
482         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
483       oss << "\nOther geometric types are :";
484       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
485         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
486       reason=oss.str();
487       return false;
488     }
489   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
490     if(_nodal_connec==0 || otherC->_nodal_connec==0)
491       {
492         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
493         return false;
494       }
495   if(_nodal_connec!=otherC->_nodal_connec)
496     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
497       {
498         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
499         return false;
500       }
501   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
502     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
503       {
504         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
505         return false;
506       }
507   if(_nodal_connec_index!=otherC->_nodal_connec_index)
508     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
509       {
510         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
511         return false;
512       }
513   return true;
514 }
515
516 /*!
517  * Checks if data arrays of this mesh (node coordinates, nodal
518  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
519  * not considered.
520  *  \param [in] other - the mesh to compare with.
521  *  \param [in] prec - precision value used to compare node coordinates.
522  *  \return bool - \a true if the two meshes are same.
523  */
524 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
525 {
526   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
527   if(!otherC)
528     return false;
529   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
530     return false;
531   if(_mesh_dim!=otherC->_mesh_dim)
532     return false;
533   if(_types!=otherC->_types)
534     return false;
535   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
536     if(_nodal_connec==0 || otherC->_nodal_connec==0)
537       return false;
538   if(_nodal_connec!=otherC->_nodal_connec)
539     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
540       return false;
541   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
542     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
543       return false;
544   if(_nodal_connec_index!=otherC->_nodal_connec_index)
545     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
546       return false;
547   return true;
548 }
549
550 /*!
551  * Checks if \a this and \a other meshes are geometrically equivalent with high
552  * probability, else an exception is thrown. The meshes are considered equivalent if
553  * (1) meshes contain the same number of nodes and the same number of elements of the
554  * same types (2) three cells of the two meshes (first, last and middle) are based
555  * on coincident nodes (with a specified precision).
556  *  \param [in] other - the mesh to compare with.
557  *  \param [in] prec - the precision used to compare nodes of the two meshes.
558  *  \throw If the two meshes do not match.
559  */
560 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
561 {
562  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
563  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
564   if(!otherC)
565     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
566 }
567
568 /*!
569  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
570  * cells each node belongs to.
571  * \warning For speed reasons, this method does not check if node ids in the nodal
572  *          connectivity correspond to the size of node coordinates array.
573  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
574  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
575  *        dividing cell ids in \a revNodal into groups each referring to one
576  *        node. Its every element (except the last one) is an index pointing to the
577  *         first id of a group of cells. For example cells sharing the node #1 are 
578  *        described by following range of indices: 
579  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
580  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
581  *        Number of cells sharing the *i*-th node is
582  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
583  * \throw If the coordinates array is not set.
584  * \throw If the nodal connectivity of cells is not defined.
585  * 
586  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
587  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
588  */
589 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
590 {
591   checkFullyDefined();
592   int nbOfNodes=getNumberOfNodes();
593   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
594   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
595   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
596   const int *conn=_nodal_connec->getConstPointer();
597   const int *connIndex=_nodal_connec_index->getConstPointer();
598   int nbOfCells=getNumberOfCells();
599   int nbOfEltsInRevNodal=0;
600   for(int eltId=0;eltId<nbOfCells;eltId++)
601     {
602       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
603       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
604       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
605         if(*iter>=0)//for polyhedrons
606           {
607             nbOfEltsInRevNodal++;
608             revNodalIndxPtr[(*iter)+1]++;
609           }
610     }
611   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
612   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
613   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
614   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
615   for(int eltId=0;eltId<nbOfCells;eltId++)
616     {
617       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
618       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
619       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
620         if(*iter>=0)//for polyhedrons
621           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
622     }
623 }
624
625 /// @cond INTERNAL
626
627 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
628 {
629   return id;
630 }
631
632 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
633 {
634   if(!compute)
635     return id+1;
636   else
637     {
638       if(cm.getOrientationStatus(nb,conn1,conn2))
639         return id+1;
640       else
641         return -(id+1);
642     }
643 }
644
645 class MinusOneSonsGenerator
646 {
647 public:
648   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
649   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
650   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
651   static const int DELTA=1;
652 private:
653   const INTERP_KERNEL::CellModel& _cm;
654 };
655
656 class MinusOneSonsGeneratorBiQuadratic
657 {
658 public:
659   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
660   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
661   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
662   static const int DELTA=1;
663 private:
664   const INTERP_KERNEL::CellModel& _cm;
665 };
666
667 class MinusTwoSonsGenerator
668 {
669 public:
670   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
671   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
672   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
673   static const int DELTA=2;
674 private:
675   const INTERP_KERNEL::CellModel& _cm;
676 };
677
678 /// @endcond
679
680 /*!
681  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
682  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
683  * describing correspondence between cells of \a this and the result meshes are
684  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
685  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
686  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
687  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
688  * \warning For speed reasons, this method does not check if node ids in the nodal
689  *          connectivity correspond to the size of node coordinates array.
690  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
691  *          to write this mesh to the MED file, its cells must be sorted using
692  *          sortCellsInMEDFileFrmt().
693  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
694  *         each cell of \a this mesh.
695  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
696  *        dividing cell ids in \a desc into groups each referring to one
697  *        cell of \a this mesh. Its every element (except the last one) is an index
698  *        pointing to the first id of a group of cells. For example cells of the
699  *        result mesh bounding the cell #1 of \a this mesh are described by following
700  *        range of indices:
701  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
702  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
703  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
704  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
705  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
706  *         by each cell of the result mesh.
707  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
708  *        in the result mesh,
709  *        dividing cell ids in \a revDesc into groups each referring to one
710  *        cell of the result mesh the same way as \a descIndx divides \a desc.
711  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
712  *        delete this mesh using decrRef() as it is no more needed.
713  *  \throw If the coordinates array is not set.
714  *  \throw If the nodal connectivity of cells is node defined.
715  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
716  *         revDescIndx == NULL.
717  * 
718  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
719  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
720  * \sa buildDescendingConnectivity2()
721  */
722 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
723 {
724   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
725 }
726
727 /*!
728  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
729  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
730  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
731  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
732  * \sa MEDCouplingUMesh::buildDescendingConnectivity
733  */
734 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
735 {
736   checkFullyDefined();
737   if(getMeshDimension()!=3)
738     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
739   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
740 }
741
742 /*!
743  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
744  * this->getMeshDimension(), that bound cells of \a this mesh. In
745  * addition arrays describing correspondence between cells of \a this and the result
746  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
747  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
748  *  mesh. This method differs from buildDescendingConnectivity() in that apart
749  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
750  * result meshes. So a positive id means that order of nodes in corresponding cells
751  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
752  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
753  * i.e. cell ids are one-based.
754  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
755  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
756  * \warning For speed reasons, this method does not check if node ids in the nodal
757  *          connectivity correspond to the size of node coordinates array.
758  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
759  *          to write this mesh to the MED file, its cells must be sorted using
760  *          sortCellsInMEDFileFrmt().
761  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
762  *         each cell of \a this mesh.
763  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
764  *        dividing cell ids in \a desc into groups each referring to one
765  *        cell of \a this mesh. Its every element (except the last one) is an index
766  *        pointing to the first id of a group of cells. For example cells of the
767  *        result mesh bounding the cell #1 of \a this mesh are described by following
768  *        range of indices:
769  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
770  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
771  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
772  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
773  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
774  *         by each cell of the result mesh.
775  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
776  *        in the result mesh,
777  *        dividing cell ids in \a revDesc into groups each referring to one
778  *        cell of the result mesh the same way as \a descIndx divides \a desc.
779  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
780  *        shares the node coordinates array with \a this mesh. The caller is to
781  *        delete this mesh using decrRef() as it is no more needed.
782  *  \throw If the coordinates array is not set.
783  *  \throw If the nodal connectivity of cells is node defined.
784  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
785  *         revDescIndx == NULL.
786  * 
787  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
788  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
789  * \sa buildDescendingConnectivity()
790  */
791 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
792 {
793   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
794 }
795
796 /*!
797  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
798  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
799  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
800  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
801  *
802  * \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
803  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
804  * \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.
805  */
806 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
807 {
808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
812   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
813   meshDM1=0;
814   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
815 }
816
817 /*!
818  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
819  * 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,
820  * excluding a set of meshdim-1 cells in input descending connectivity.
821  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
822  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
823  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
824  *
825  * \param [in] desc descending connectivity array.
826  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
827  * \param [in] revDesc reverse descending connectivity array.
828  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
829  * \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
830  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
831  * \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.
832  */
833 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
834                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
835 {
836   if(!desc || !descIndx || !revDesc || !revDescIndx)
837     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
838   const int *descPtr=desc->getConstPointer();
839   const int *descIPtr=descIndx->getConstPointer();
840   const int *revDescPtr=revDesc->getConstPointer();
841   const int *revDescIPtr=revDescIndx->getConstPointer();
842   //
843   int nbCells=descIndx->getNumberOfTuples()-1;
844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
845   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
846   int *out1Ptr=out1->getPointer();
847   *out1Ptr++=0;
848   out0->reserve(desc->getNumberOfTuples());
849   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
850     {
851       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
852         {
853           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
854           s.erase(i);
855           out0->insertAtTheEnd(s.begin(),s.end());
856         }
857       *out1Ptr=out0->getNumberOfTuples();
858     }
859   neighbors=out0.retn();
860   neighborsIndx=out1.retn();
861 }
862
863 /// @cond INTERNAL
864
865 /*!
866  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
867  * For speed reasons no check of this will be done.
868  */
869 template<class SonsGenerator>
870 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
871 {
872   if(!desc || !descIndx || !revDesc || !revDescIndx)
873     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
874   checkConnectivityFullyDefined();
875   int nbOfCells=getNumberOfCells();
876   int nbOfNodes=getNumberOfNodes();
877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
878   int *revNodalIndxPtr=revNodalIndx->getPointer();
879   const int *conn=_nodal_connec->getConstPointer();
880   const int *connIndex=_nodal_connec_index->getConstPointer();
881   std::string name="Mesh constituent of "; name+=getName();
882   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
883   ret->setCoords(getCoords());
884   ret->allocateCells(2*nbOfCells);
885   descIndx->alloc(nbOfCells+1,1);
886   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
887   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
888   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
889     {
890       int pos=connIndex[eltId];
891       int posP1=connIndex[eltId+1];
892       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
893       SonsGenerator sg(cm);
894       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
895       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
896       for(unsigned i=0;i<nbOfSons;i++)
897         {
898           INTERP_KERNEL::NormalizedCellType cmsId;
899           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
900           for(unsigned k=0;k<nbOfNodesSon;k++)
901             if(tmp[k]>=0)
902               revNodalIndxPtr[tmp[k]+1]++;
903           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
904           revDesc2->pushBackSilent(eltId);
905         }
906       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
907     }
908   int nbOfCellsM1=ret->getNumberOfCells();
909   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
910   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
911   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
912   int *revNodalPtr=revNodal->getPointer();
913   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
914   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
915   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
916     {
917       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
918       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
919       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
920         if(*iter>=0)//for polyhedrons
921           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
922     }
923   //
924   DataArrayInt *commonCells=0,*commonCellsI=0;
925   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
926   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
927   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
928   int newNbOfCellsM1=-1;
929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
930                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
931   std::vector<bool> isImpacted(nbOfCellsM1,false);
932   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
933     for(int work2=work[0];work2!=work[1];work2++)
934       isImpacted[commonCellsPtr[work2]]=true;
935   const int *o2nM1Ptr=o2nM1->getConstPointer();
936   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
937   const int *n2oM1Ptr=n2oM1->getConstPointer();
938   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
939   ret2->copyTinyInfoFrom(this);
940   desc->alloc(descIndx->back(),1);
941   int *descPtr=desc->getPointer();
942   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
943   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
944     {
945       if(!isImpacted[i])
946         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
947       else
948         {
949           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
950             {
951               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
952               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
953             }
954           else
955             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
956         }
957     }
958   revDesc->reserve(newNbOfCellsM1);
959   revDescIndx->alloc(newNbOfCellsM1+1,1);
960   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
961   const int *revDesc2Ptr=revDesc2->getConstPointer();
962   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
963     {
964       int oldCellIdM1=n2oM1Ptr[i];
965       if(!isImpacted[oldCellIdM1])
966         {
967           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
968           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
969         }
970       else
971         {
972           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
973             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
974           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
975           commonCellsIPtr++;
976         }
977     }
978   //
979   return ret2.retn();
980 }
981
982 struct MEDCouplingAccVisit
983 {
984   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
985   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
986   int _new_nb_of_nodes;
987 };
988
989 /// @endcond
990
991 /*!
992  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
993  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
994  * array of cell ids. Pay attention that after conversion all algorithms work slower
995  * with \a this mesh than before conversion. <br> If an exception is thrown during the
996  * conversion due presence of invalid ids in the array of cells to convert, as a
997  * result \a this mesh contains some already converted elements. In this case the 2D
998  * mesh remains valid but 3D mesh becomes \b inconsistent!
999  *  \warning This method can significantly modify the order of geometric types in \a this,
1000  *          hence, to write this mesh to the MED file, its cells must be sorted using
1001  *          sortCellsInMEDFileFrmt().
1002  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1003  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1004  *         cellIdsToConvertBg.
1005  *  \throw If the coordinates array is not set.
1006  *  \throw If the nodal connectivity of cells is node defined.
1007  *  \throw If dimension of \a this mesh is not either 2 or 3.
1008  *
1009  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1010  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1011  */
1012 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1013 {
1014   checkFullyDefined();
1015   int dim=getMeshDimension();
1016   if(dim<2 || dim>3)
1017     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1018   int nbOfCells=getNumberOfCells();
1019   if(dim==2)
1020     {
1021       const int *connIndex=_nodal_connec_index->getConstPointer();
1022       int *conn=_nodal_connec->getPointer();
1023       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1024         {
1025           if(*iter>=0 && *iter<nbOfCells)
1026             {
1027               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1028               if(!cm.isQuadratic())
1029                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1030               else
1031                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1032             }
1033           else
1034             {
1035               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1036               oss << " in range [0," << nbOfCells << ") !";
1037               throw INTERP_KERNEL::Exception(oss.str().c_str());
1038             }
1039         }
1040     }
1041   else
1042     {
1043       int *connIndex=_nodal_connec_index->getPointer();
1044       int connIndexLgth=_nodal_connec_index->getNbOfElems();
1045       const int *connOld=_nodal_connec->getConstPointer();
1046       int connOldLgth=_nodal_connec->getNbOfElems();
1047       std::vector<int> connNew(connOld,connOld+connOldLgth);
1048       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1049         {
1050           if(*iter>=0 && *iter<nbOfCells)
1051             {
1052               int pos=connIndex[*iter];
1053               int posP1=connIndex[(*iter)+1];
1054               int lgthOld=posP1-pos-1;
1055               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1056               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1057               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1058               int *tmp=new int[nbOfFaces*lgthOld];
1059               int *work=tmp;
1060               for(int j=0;j<(int)nbOfFaces;j++)
1061                 {
1062                   INTERP_KERNEL::NormalizedCellType type;
1063                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1064                   work+=offset;
1065                   *work++=-1;
1066                 }
1067               std::size_t newLgth=std::distance(tmp,work)-1;
1068               std::size_t delta=newLgth-lgthOld;
1069               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1070               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1071               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1072               delete [] tmp;
1073             }
1074           else
1075             {
1076               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1077               oss << " in range [0," << nbOfCells << ") !";
1078               throw INTERP_KERNEL::Exception(oss.str().c_str());
1079             }
1080         }
1081       _nodal_connec->alloc((int)connNew.size(),1);
1082       int *newConnPtr=_nodal_connec->getPointer();
1083       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1084     }
1085   computeTypes();
1086 }
1087
1088 /*!
1089  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1090  * polyhedrons (if \a this is a 3D mesh).
1091  *  \warning As this method is purely for user-friendliness and no optimization is
1092  *          done to avoid construction of a useless vector, this method can be costly
1093  *          in memory.
1094  *  \throw If the coordinates array is not set.
1095  *  \throw If the nodal connectivity of cells is node defined.
1096  *  \throw If dimension of \a this mesh is not either 2 or 3.
1097  */
1098 void MEDCouplingUMesh::convertAllToPoly()
1099 {
1100   int nbOfCells=getNumberOfCells();
1101   std::vector<int> cellIds(nbOfCells);
1102   for(int i=0;i<nbOfCells;i++)
1103     cellIds[i]=i;
1104   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1105 }
1106
1107 /*!
1108  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1109  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1110  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1111  * base facet of the volume and the second half of nodes describes an opposite facet
1112  * having the same number of nodes as the base one. This method converts such
1113  * connectivity to a valid polyhedral format where connectivity of each facet is
1114  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1115  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1116  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1117  * a correct orientation of the first facet of a polyhedron, else orientation of a
1118  * corrected cell is reverse.<br>
1119  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1120  * it releases the user from boring description of polyhedra connectivity in the valid
1121  * format.
1122  *  \throw If \a this->getMeshDimension() != 3.
1123  *  \throw If \a this->getSpaceDimension() != 3.
1124  *  \throw If the nodal connectivity of cells is not defined.
1125  *  \throw If the coordinates array is not set.
1126  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1127  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1128  *
1129  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1130  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1131  */
1132 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1133 {
1134   checkFullyDefined();
1135   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1136     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1137   int nbOfCells=getNumberOfCells();
1138   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1139   newCi->alloc(nbOfCells+1,1);
1140   int *newci=newCi->getPointer();
1141   const int *ci=_nodal_connec_index->getConstPointer();
1142   const int *c=_nodal_connec->getConstPointer();
1143   newci[0]=0;
1144   for(int i=0;i<nbOfCells;i++)
1145     {
1146       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1147       if(type==INTERP_KERNEL::NORM_POLYHED)
1148         {
1149           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1150             {
1151               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1152               throw INTERP_KERNEL::Exception(oss.str().c_str());
1153             }
1154           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1155           if(n2%2!=0)
1156             {
1157               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 !";
1158               throw INTERP_KERNEL::Exception(oss.str().c_str());
1159             }
1160           int n1=(int)(n2/2);
1161           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)
1162         }
1163       else
1164         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1165     }
1166   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1167   newC->alloc(newci[nbOfCells],1);
1168   int *newc=newC->getPointer();
1169   for(int i=0;i<nbOfCells;i++)
1170     {
1171       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1172       if(type==INTERP_KERNEL::NORM_POLYHED)
1173         {
1174           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1175           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1176           *newc++=-1;
1177           for(std::size_t j=0;j<n1;j++)
1178             {
1179               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1180               newc[n1+5*j]=-1;
1181               newc[n1+5*j+1]=c[ci[i]+1+j];
1182               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1183               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1184               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1185             }
1186           newc+=n1*6;
1187         }
1188       else
1189         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1190     }
1191   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1192   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1193 }
1194
1195
1196 /*!
1197  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1198  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1199  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1200  *          to write this mesh to the MED file, its cells must be sorted using
1201  *          sortCellsInMEDFileFrmt().
1202  * \return \c true if at least one cell has been converted, \c false else. In the
1203  *         last case the nodal connectivity remains unchanged.
1204  * \throw If the coordinates array is not set.
1205  * \throw If the nodal connectivity of cells is not defined.
1206  * \throw If \a this->getMeshDimension() < 0.
1207  */
1208 bool MEDCouplingUMesh::unPolyze()
1209 {
1210   checkFullyDefined();
1211   int mdim=getMeshDimension();
1212   if(mdim<0)
1213     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1214   if(mdim<=1)
1215     return false;
1216   int nbOfCells=getNumberOfCells();
1217   if(nbOfCells<1)
1218     return false;
1219   int initMeshLgth=getMeshLength();
1220   int *conn=_nodal_connec->getPointer();
1221   int *index=_nodal_connec_index->getPointer();
1222   int posOfCurCell=0;
1223   int newPos=0;
1224   int lgthOfCurCell;
1225   bool ret=false;
1226   for(int i=0;i<nbOfCells;i++)
1227     {
1228       lgthOfCurCell=index[i+1]-posOfCurCell;
1229       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1231       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1232       int newLgth;
1233       if(cm.isDynamic())
1234         {
1235           switch(cm.getDimension())
1236             {
1237             case 2:
1238               {
1239                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1240                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1241                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1242                 break;
1243               }
1244             case 3:
1245               {
1246                 int nbOfFaces,lgthOfPolyhConn;
1247                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1248                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1249                 break;
1250               }
1251             case 1:
1252               {
1253                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1254                 break;
1255               }
1256             }
1257           ret=ret || (newType!=type);
1258           conn[newPos]=newType;
1259           newPos+=newLgth+1;
1260           posOfCurCell=index[i+1];
1261           index[i+1]=newPos;
1262         }
1263       else
1264         {
1265           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1266           newPos+=lgthOfCurCell;
1267           posOfCurCell+=lgthOfCurCell;
1268           index[i+1]=newPos;
1269         }
1270     }
1271   if(newPos!=initMeshLgth)
1272     _nodal_connec->reAlloc(newPos);
1273   if(ret)
1274     computeTypes();
1275   return ret;
1276 }
1277
1278 /*!
1279  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1280  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1281  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1282  *
1283  * \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 
1284  *             precision.
1285  */
1286 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1287 {
1288   checkFullyDefined();
1289   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1290     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1291   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1292   coords->recenterForMaxPrecision(eps);
1293   //
1294   int nbOfCells=getNumberOfCells();
1295   const int *conn=_nodal_connec->getConstPointer();
1296   const int *index=_nodal_connec_index->getConstPointer();
1297   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1298   connINew->alloc(nbOfCells+1,1);
1299   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1300   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1301   bool changed=false;
1302   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1303     {
1304       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1305         {
1306           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1307           changed=true;
1308         }
1309       else
1310         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1311       *connINewPtr=connNew->getNumberOfTuples();
1312     }
1313   if(changed)
1314     setConnectivity(connNew,connINew,false);
1315 }
1316
1317 /*!
1318  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1319  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1320  * the format of returned DataArrayInt instance.
1321  * 
1322  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1323  * \sa MEDCouplingUMesh::getNodeIdsInUse
1324  */
1325 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1326 {
1327   checkConnectivityFullyDefined();
1328   int nbOfCells=getNumberOfCells();
1329   const int *connIndex=_nodal_connec_index->getConstPointer();
1330   const int *conn=_nodal_connec->getConstPointer();
1331   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1332   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1333   std::vector<bool> retS(maxElt,false);
1334   for(int i=0;i<nbOfCells;i++)
1335     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1336       if(conn[j]>=0)
1337         retS[conn[j]]=true;
1338   int sz=0;
1339   for(int i=0;i<maxElt;i++)
1340     if(retS[i])
1341       sz++;
1342   DataArrayInt *ret=DataArrayInt::New();
1343   ret->alloc(sz,1);
1344   int *retPtr=ret->getPointer();
1345   for(int i=0;i<maxElt;i++)
1346     if(retS[i])
1347       *retPtr++=i;
1348   return ret;
1349 }
1350
1351 /*!
1352  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1353  * \sa MEDCouplingUMesh::getNodeIdsInUse
1354  */
1355 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1356 {
1357   int nbOfNodes=(int)nodeIdsInUse.size();
1358   int nbOfCells=getNumberOfCells();
1359   const int *connIndex=_nodal_connec_index->getConstPointer();
1360   const int *conn=_nodal_connec->getConstPointer();
1361   for(int i=0;i<nbOfCells;i++)
1362     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1363       if(conn[j]>=0)
1364         {
1365           if(conn[j]<nbOfNodes)
1366             nodeIdsInUse[conn[j]]=true;
1367           else
1368             {
1369               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1370               throw INTERP_KERNEL::Exception(oss.str().c_str());
1371             }
1372         }
1373 }
1374
1375 /*!
1376  * Finds nodes not used in any cell and returns an array giving a new id to every node
1377  * by excluding the unused nodes, for which the array holds -1. The result array is
1378  * a mapping in "Old to New" mode. 
1379  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1380  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1381  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1382  *          if the node is unused or a new id else. The caller is to delete this
1383  *          array using decrRef() as it is no more needed.  
1384  *  \throw If the coordinates array is not set.
1385  *  \throw If the nodal connectivity of cells is not defined.
1386  *  \throw If the nodal connectivity includes an invalid id.
1387  *
1388  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1389  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1390  * \sa computeNodeIdsAlg()
1391  */
1392 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1393 {
1394   nbrOfNodesInUse=-1;
1395   int nbOfNodes=getNumberOfNodes();
1396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1397   ret->alloc(nbOfNodes,1);
1398   int *traducer=ret->getPointer();
1399   std::fill(traducer,traducer+nbOfNodes,-1);
1400   int nbOfCells=getNumberOfCells();
1401   const int *connIndex=_nodal_connec_index->getConstPointer();
1402   const int *conn=_nodal_connec->getConstPointer();
1403   for(int i=0;i<nbOfCells;i++)
1404     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1405       if(conn[j]>=0)
1406         {
1407           if(conn[j]<nbOfNodes)
1408             traducer[conn[j]]=1;
1409           else
1410             {
1411               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1412               throw INTERP_KERNEL::Exception(oss.str().c_str());
1413             }
1414         }
1415   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1416   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1417   return ret.retn();
1418 }
1419
1420 /*!
1421  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1422  * For each cell in \b this the number of nodes constituting cell is computed.
1423  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1424  * So for pohyhedrons some nodes can be counted several times in the returned result.
1425  * 
1426  * \return a newly allocated array
1427  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1428  */
1429 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1430 {
1431   checkConnectivityFullyDefined();
1432   int nbOfCells=getNumberOfCells();
1433   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1434   ret->alloc(nbOfCells,1);
1435   int *retPtr=ret->getPointer();
1436   const int *conn=getNodalConnectivity()->getConstPointer();
1437   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1438   for(int i=0;i<nbOfCells;i++,retPtr++)
1439     {
1440       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1441         *retPtr=connI[i+1]-connI[i]-1;
1442       else
1443         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1444     }
1445   return ret.retn();
1446 }
1447
1448 /*!
1449  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1450  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1451  *
1452  * \return DataArrayInt * - new object to be deallocated by the caller.
1453  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1454  */
1455 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1456 {
1457   checkConnectivityFullyDefined();
1458   int nbOfCells=getNumberOfCells();
1459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1460   ret->alloc(nbOfCells,1);
1461   int *retPtr=ret->getPointer();
1462   const int *conn=getNodalConnectivity()->getConstPointer();
1463   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1464   for(int i=0;i<nbOfCells;i++,retPtr++)
1465     {
1466       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1467       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1468         *retPtr=(int)s.size();
1469       else
1470         {
1471           s.erase(-1);
1472           *retPtr=(int)s.size();
1473         }
1474     }
1475   return ret.retn();
1476 }
1477
1478 /*!
1479  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1480  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1481  * 
1482  * \return a newly allocated array
1483  */
1484 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1485 {
1486   checkConnectivityFullyDefined();
1487   int nbOfCells=getNumberOfCells();
1488   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1489   ret->alloc(nbOfCells,1);
1490   int *retPtr=ret->getPointer();
1491   const int *conn=getNodalConnectivity()->getConstPointer();
1492   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1493   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1494     {
1495       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1496       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1497     }
1498   return ret.retn();
1499 }
1500
1501 /*!
1502  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1503  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1504  * array mean that the corresponding old node is no more used. 
1505  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1506  *           this->getNumberOfNodes() before call of this method. The caller is to
1507  *           delete this array using decrRef() as it is no more needed. 
1508  *  \throw If the coordinates array is not set.
1509  *  \throw If the nodal connectivity of cells is not defined.
1510  *  \throw If the nodal connectivity includes an invalid id.
1511  *
1512  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1513  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1514  */
1515 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1516 {
1517   return MEDCouplingPointSet::zipCoordsTraducer();
1518 }
1519
1520 /*!
1521  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1522  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1523  */
1524 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1525 {
1526   switch(compType)
1527     {
1528     case 0:
1529       return AreCellsEqual0(conn,connI,cell1,cell2);
1530     case 1:
1531       return AreCellsEqual1(conn,connI,cell1,cell2);
1532     case 2:
1533       return AreCellsEqual2(conn,connI,cell1,cell2);
1534     case 3:
1535       return AreCellsEqual3(conn,connI,cell1,cell2);
1536     case 7:
1537       return AreCellsEqual7(conn,connI,cell1,cell2);
1538     }
1539   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1540 }
1541
1542 /*!
1543  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1544  */
1545 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1546 {
1547   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1548     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1549   return 0;
1550 }
1551
1552 /*!
1553  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1554  */
1555 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1556 {
1557   int sz=connI[cell1+1]-connI[cell1];
1558   if(sz==connI[cell2+1]-connI[cell2])
1559     {
1560       if(conn[connI[cell1]]==conn[connI[cell2]])
1561         {
1562           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1563           unsigned dim=cm.getDimension();
1564           if(dim!=3)
1565             {
1566               if(dim!=1)
1567                 {
1568                   int sz1=2*(sz-1);
1569                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1570                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1571                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1572                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1573                   return work!=tmp+sz1?1:0;
1574                 }
1575               else
1576                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1577             }
1578           else
1579             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1580         }
1581     }
1582   return 0;
1583 }
1584
1585 /*!
1586  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1587  */
1588 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1589 {
1590   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1591     {
1592       if(conn[connI[cell1]]==conn[connI[cell2]])
1593         {
1594           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1595           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1596           return s1==s2?1:0;
1597         }
1598     }
1599   return 0;
1600 }
1601
1602 /*!
1603  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1604  */
1605 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1606 {
1607   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1608     {
1609       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1610       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1611       return s1==s2?1:0;
1612     }
1613   return 0;
1614 }
1615
1616 /*!
1617  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1618  */
1619 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1620 {
1621   int sz=connI[cell1+1]-connI[cell1];
1622   if(sz==connI[cell2+1]-connI[cell2])
1623     {
1624       if(conn[connI[cell1]]==conn[connI[cell2]])
1625         {
1626           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1627           unsigned dim=cm.getDimension();
1628           if(dim!=3)
1629             {
1630               if(dim!=1)
1631                 {
1632                   int sz1=2*(sz-1);
1633                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1634                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1635                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1636                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1637                   if(work!=tmp+sz1)
1638                     return 1;
1639                   else
1640                     {
1641                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1642                       std::reverse_iterator<int *> it2((int *)tmp);
1643                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1644                         return 2;
1645                       else
1646                         return 0;
1647                     }
1648                   
1649                   return work!=tmp+sz1?1:0;
1650                 }
1651               else
1652                 {//case of SEG2 and SEG3
1653                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1654                     return 1;
1655                   if(!cm.isQuadratic())
1656                     {
1657                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1658                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1659                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1660                         return 2;
1661                       return 0;
1662                     }
1663                   else
1664                     {
1665                       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])
1666                         return 2;
1667                       return 0;
1668                     }
1669                 }
1670             }
1671           else
1672             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1673         }
1674     }
1675   return 0;
1676 }
1677
1678 /*!
1679  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1680  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1681  * and result remains unchanged.
1682  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1683  * If in 'candidates' pool -1 value is considered as an empty value.
1684  * WARNING this method returns only ONE set of result !
1685  */
1686 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1687 {
1688   if(candidates.size()<1)
1689     return false;
1690   bool ret=false;
1691   std::vector<int>::const_iterator iter=candidates.begin();
1692   int start=(*iter++);
1693   for(;iter!=candidates.end();iter++)
1694     {
1695       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1696       if(status!=0)
1697         {
1698           if(!ret)
1699             {
1700               result->pushBackSilent(start);
1701               ret=true;
1702             }
1703           if(status==1)
1704             result->pushBackSilent(*iter);
1705           else
1706             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1707         }
1708     }
1709   return ret;
1710 }
1711
1712 /*!
1713  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1714  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1715  *
1716  * \param [in] compType input specifying the technique used to compare cells each other.
1717  *   - 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.
1718  *   - 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)
1719  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1720  *   - 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
1721  * can be used for users not sensitive to orientation of cell
1722  * \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.
1723  * \param [out] commonCells
1724  * \param [out] commonCellsI
1725  * \return the correspondance array old to new in a newly allocated array.
1726  * 
1727  */
1728 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1729 {
1730   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1731   getReverseNodalConnectivity(revNodal,revNodalI);
1732   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1733 }
1734
1735 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1736                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1737 {
1738   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1739   int nbOfCells=nodalI->getNumberOfTuples()-1;
1740   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1741   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1742   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1743   std::vector<bool> isFetched(nbOfCells,false);
1744   if(startCellId==0)
1745     {
1746       for(int i=0;i<nbOfCells;i++)
1747         {
1748           if(!isFetched[i])
1749             {
1750               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1751               std::vector<int> v,v2;
1752               if(connOfNode!=connPtr+connIPtr[i+1])
1753                 {
1754                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1755                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1756                   connOfNode++;
1757                 }
1758               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1759                 if(*connOfNode>=0)
1760                   {
1761                     v=v2;
1762                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1763                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1764                     v2.resize(std::distance(v2.begin(),it));
1765                   }
1766               if(v2.size()>1)
1767                 {
1768                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1769                     {
1770                       int pos=commonCellsI->back();
1771                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1772                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1773                         isFetched[*it]=true;
1774                     }
1775                 }
1776             }
1777         }
1778     }
1779   else
1780     {
1781       for(int i=startCellId;i<nbOfCells;i++)
1782         {
1783           if(!isFetched[i])
1784             {
1785               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1786               std::vector<int> v,v2;
1787               if(connOfNode!=connPtr+connIPtr[i+1])
1788                 {
1789                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1790                   connOfNode++;
1791                 }
1792               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1793                 if(*connOfNode>=0)
1794                   {
1795                     v=v2;
1796                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1797                     v2.resize(std::distance(v2.begin(),it));
1798                   }
1799               if(v2.size()>1)
1800                 {
1801                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1802                     {
1803                       int pos=commonCellsI->back();
1804                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1805                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1806                         isFetched[*it]=true;
1807                     }
1808                 }
1809             }
1810         }
1811     }
1812   commonCellsArr=commonCells.retn();
1813   commonCellsIArr=commonCellsI.retn();
1814 }
1815
1816 /*!
1817  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1818  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1819  * than \a other->getNumberOfCells() in the returned array means that there is no
1820  * corresponding cell in \a this mesh.
1821  * It is expected that \a this and \a other meshes share the same node coordinates
1822  * array, if it is not so an exception is thrown. 
1823  *  \param [in] other - the mesh to compare with.
1824  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1825  *         valid values [0,1,2], see zipConnectivityTraducer().
1826  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1827  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1828  *         values. The caller is to delete this array using
1829  *         decrRef() as it is no more needed.
1830  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1831  *         mesh.
1832  *
1833  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1834  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1835  *  \sa checkDeepEquivalOnSameNodesWith()
1836  *  \sa checkGeoEquivalWith()
1837  */
1838 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1839 {
1840   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1841   int nbOfCells=getNumberOfCells();
1842   static const int possibleCompType[]={0,1,2};
1843   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1844     {
1845       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1846       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1847       oss << " !";
1848       throw INTERP_KERNEL::Exception(oss.str().c_str());
1849     }
1850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1851   arr=o2n->substr(nbOfCells);
1852   arr->setName(other->getName());
1853   int tmp;
1854   if(other->getNumberOfCells()==0)
1855     return true;
1856   return arr->getMaxValue(tmp)<nbOfCells;
1857 }
1858
1859 /*!
1860  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1861  * This method tries to determine if \b other is fully included in \b this.
1862  * The main difference is that this method is not expected to throw exception.
1863  * This method has two outputs :
1864  *
1865  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1866  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1867  */
1868 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1869 {
1870   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1871   DataArrayInt *commonCells=0,*commonCellsI=0;
1872   int thisNbCells=getNumberOfCells();
1873   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1874   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1875   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1876   int otherNbCells=other->getNumberOfCells();
1877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1878   arr2->alloc(otherNbCells,1);
1879   arr2->fillWithZero();
1880   int *arr2Ptr=arr2->getPointer();
1881   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1882   for(int i=0;i<nbOfCommon;i++)
1883     {
1884       int start=commonCellsPtr[commonCellsIPtr[i]];
1885       if(start<thisNbCells)
1886         {
1887           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1888             {
1889               int sig=commonCellsPtr[j]>0?1:-1;
1890               int val=std::abs(commonCellsPtr[j])-1;
1891               if(val>=thisNbCells)
1892                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1893             }
1894         }
1895     }
1896   arr2->setName(other->getName());
1897   if(arr2->presenceOfValue(0))
1898     return false;
1899   arr=arr2.retn();
1900   return true;
1901 }
1902
1903 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1904 {
1905   if(!other)
1906     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1907   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1908   if(!otherC)
1909     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1910   std::vector<const MEDCouplingUMesh *> ms(2);
1911   ms[0]=this;
1912   ms[1]=otherC;
1913   return MergeUMeshesOnSameCoords(ms);
1914 }
1915
1916 /*!
1917  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1918  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1919  * cellIds is not given explicitely but by a range python like.
1920  * 
1921  * \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.
1922  * \return a newly allocated
1923  * 
1924  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1925  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1926  */
1927 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1928 {
1929   if(getMeshDimension()!=-1)
1930     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1931   else
1932     {
1933       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1934       if(newNbOfCells!=1)
1935         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1936       if(start!=0)
1937         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1938       incrRef();
1939       return const_cast<MEDCouplingUMesh *>(this);
1940     }
1941 }
1942
1943 /*!
1944  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1945  * The result mesh shares or not the node coordinates array with \a this mesh depending
1946  * on \a keepCoords parameter.
1947  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1948  *           to write this mesh to the MED file, its cells must be sorted using
1949  *           sortCellsInMEDFileFrmt().
1950  *  \param [in] begin - an array of cell ids to include to the new mesh.
1951  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1952  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1953  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1954  *         by calling zipCoords().
1955  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1956  *         to delete this mesh using decrRef() as it is no more needed. 
1957  *  \throw If the coordinates array is not set.
1958  *  \throw If the nodal connectivity of cells is not defined.
1959  *  \throw If any cell id in the array \a begin is not valid.
1960  *
1961  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1962  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1963  */
1964 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1965 {
1966   if(getMeshDimension()!=-1)
1967     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1968   else
1969     {
1970       if(end-begin!=1)
1971         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1972       if(begin[0]!=0)
1973         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1974       incrRef();
1975       return const_cast<MEDCouplingUMesh *>(this);
1976     }
1977 }
1978
1979 /*!
1980  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1981  *
1982  * 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.
1983  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1984  * The number of cells of \b this will remain the same with this method.
1985  *
1986  * \param [in] begin begin of cell ids (included) of cells in this to assign
1987  * \param [in] end end of cell ids (excluded) of cells in this to assign
1988  * \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 ).
1989  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1990  */
1991 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1992 {
1993   checkConnectivityFullyDefined();
1994   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1995   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1996     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1997   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1998     {
1999       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2000       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2001       throw INTERP_KERNEL::Exception(oss.str().c_str());
2002     }
2003   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2004   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2005     {
2006       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2007       throw INTERP_KERNEL::Exception(oss.str().c_str());
2008     }
2009   int nbOfCells=getNumberOfCells();
2010   bool easyAssign=true;
2011   const int *connI=_nodal_connec_index->getConstPointer();
2012   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2013   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2014     {
2015       if(*it>=0 && *it<nbOfCells)
2016         {
2017           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2018         }
2019       else
2020         {
2021           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2022           throw INTERP_KERNEL::Exception(oss.str().c_str());
2023         }
2024     }
2025   if(easyAssign)
2026     {
2027       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2028       computeTypes();
2029     }
2030   else
2031     {
2032       DataArrayInt *arrOut=0,*arrIOut=0;
2033       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2034                                                arrOut,arrIOut);
2035       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2036       setConnectivity(arrOut,arrIOut,true);
2037     }
2038 }
2039
2040 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2041 {
2042   checkConnectivityFullyDefined();
2043   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2044   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2045     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2046   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2047     {
2048       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2049       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2050       throw INTERP_KERNEL::Exception(oss.str().c_str());
2051     }
2052   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2053   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2054     {
2055       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2056       throw INTERP_KERNEL::Exception(oss.str().c_str());
2057     }
2058   int nbOfCells=getNumberOfCells();
2059   bool easyAssign=true;
2060   const int *connI=_nodal_connec_index->getConstPointer();
2061   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2062   int it=start;
2063   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2064     {
2065       if(it>=0 && it<nbOfCells)
2066         {
2067           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2068         }
2069       else
2070         {
2071           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2072           throw INTERP_KERNEL::Exception(oss.str().c_str());
2073         }
2074     }
2075   if(easyAssign)
2076     {
2077       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2078       computeTypes();
2079     }
2080   else
2081     {
2082       DataArrayInt *arrOut=0,*arrIOut=0;
2083       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2084                                                 arrOut,arrIOut);
2085       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2086       setConnectivity(arrOut,arrIOut,true);
2087     }
2088 }                      
2089
2090 /*!
2091  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2092  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2093  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2094  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2095  *
2096  * \param [in] begin input start of array of node ids.
2097  * \param [in] end input end of array of node ids.
2098  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2099  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2100  */
2101 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2102 {
2103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2104   checkConnectivityFullyDefined();
2105   int tmp=-1;
2106   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2107   std::vector<bool> fastFinder(sz,false);
2108   for(const int *work=begin;work!=end;work++)
2109     if(*work>=0 && *work<sz)
2110       fastFinder[*work]=true;
2111   int nbOfCells=getNumberOfCells();
2112   const int *conn=getNodalConnectivity()->getConstPointer();
2113   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2114   for(int i=0;i<nbOfCells;i++)
2115     {
2116       int ref=0,nbOfHit=0;
2117       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2118         if(*work2>=0)
2119           {
2120             ref++;
2121             if(fastFinder[*work2])
2122               nbOfHit++;
2123           }
2124       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2125         cellIdsKept->pushBackSilent(i);
2126     }
2127   cellIdsKeptArr=cellIdsKept.retn();
2128 }
2129
2130 /*!
2131  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2132  * this->getMeshDimension(), that bound some cells of \a this mesh.
2133  * The cells of lower dimension to include to the result mesh are selected basing on
2134  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2135  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2136  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2137  * created mesh shares the node coordinates array with \a this mesh. 
2138  *  \param [in] begin - the array of node ids.
2139  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2140  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2141  *         array \a begin are added, else cells whose any node is in the
2142  *         array \a begin are added.
2143  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2144  *         to delete this mesh using decrRef() as it is no more needed. 
2145  *  \throw If the coordinates array is not set.
2146  *  \throw If the nodal connectivity of cells is not defined.
2147  *  \throw If any node id in \a begin is not valid.
2148  *
2149  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2150  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2151  */
2152 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2153 {
2154   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2155   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2156   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2157   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2158   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2159 }
2160
2161 /*!
2162  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2163  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2164  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2165  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2166  *         by calling zipCoords().
2167  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2168  *         to delete this mesh using decrRef() as it is no more needed. 
2169  *  \throw If the coordinates array is not set.
2170  *  \throw If the nodal connectivity of cells is not defined.
2171  *
2172  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2173  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2174  */
2175 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2176 {
2177   DataArrayInt *desc=DataArrayInt::New();
2178   DataArrayInt *descIndx=DataArrayInt::New();
2179   DataArrayInt *revDesc=DataArrayInt::New();
2180   DataArrayInt *revDescIndx=DataArrayInt::New();
2181   //
2182   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2183   revDesc->decrRef();
2184   desc->decrRef();
2185   descIndx->decrRef();
2186   int nbOfCells=meshDM1->getNumberOfCells();
2187   const int *revDescIndxC=revDescIndx->getConstPointer();
2188   std::vector<int> boundaryCells;
2189   for(int i=0;i<nbOfCells;i++)
2190     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2191       boundaryCells.push_back(i);
2192   revDescIndx->decrRef();
2193   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2194   return ret;
2195 }
2196
2197 /*!
2198  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2199  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2200  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2201  */
2202 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2203 {
2204   checkFullyDefined();
2205   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2206   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2207   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2208   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2209   //
2210   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2211   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2212   //
2213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2214   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2215   const int *revDescPtr=revDesc->getConstPointer();
2216   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2217   int nbOfCells=getNumberOfCells();
2218   std::vector<bool> ret1(nbOfCells,false);
2219   int sz=0;
2220   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2221     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2222       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2223   //
2224   DataArrayInt *ret2=DataArrayInt::New();
2225   ret2->alloc(sz,1);
2226   int *ret2Ptr=ret2->getPointer();
2227   sz=0;
2228   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2229     if(*it)
2230       *ret2Ptr++=sz;
2231   ret2->setName("BoundaryCells");
2232   return ret2;
2233 }
2234
2235 /*!
2236  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2237  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2238  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2239  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2240  *
2241  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2242  * This method method returns cells ids set s = s1 + s2 where :
2243  * 
2244  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2245  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2246  *
2247  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2248  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2249  *
2250  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2251  * \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
2252  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2253  */
2254 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2255 {
2256   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2257     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2258   checkConnectivityFullyDefined();
2259   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2260   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2261     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2262   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2263   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2264   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2266   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2267   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2268   DataArrayInt *idsOtherInConsti=0;
2269   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2271   if(!b)
2272     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2273   std::set<int> s1;
2274   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2275     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2278   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2279   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2281   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2282   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2283   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2284   neighThisPartAuto=0;
2285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2286   const int li[2]={0,1};
2287   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2288   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2290   s_renum1->sort();
2291   //
2292   cellIdsRk0=s0arr.retn();
2293   cellIdsRk1=s_renum1.retn();
2294 }
2295
2296 /*!
2297  * 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
2298  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2299  * 
2300  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2301  */
2302 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2303 {
2304   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2308   //
2309   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2310   revDesc=0; desc=0; descIndx=0;
2311   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2312   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2313   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2314 }
2315
2316 /*!
2317  * Finds nodes lying on the boundary of \a this mesh.
2318  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2319  *          nodes. The caller is to delete this array using decrRef() as it is no
2320  *          more needed.
2321  *  \throw If the coordinates array is not set.
2322  *  \throw If the nodal connectivity of cells is node defined.
2323  *
2324  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2325  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2326  */
2327 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2328 {
2329   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2330   return skin->computeFetchedNodeIds();
2331 }
2332
2333 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2334 {
2335   incrRef();
2336   return const_cast<MEDCouplingUMesh *>(this);
2337 }
2338
2339 /*!
2340  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2341  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2342  * 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.
2343  * 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.
2344  * 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.
2345  *
2346  * \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
2347  *             parameter is altered during the call.
2348  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2349  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2350  * \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.
2351  *
2352  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2353  */
2354 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2355                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2356 {
2357   checkFullyDefined();
2358   otherDimM1OnSameCoords.checkFullyDefined();
2359   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2360     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2361   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2362     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2363   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2364   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2367   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2368   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2372   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2373   //
2374   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2376   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2377   DataArrayInt *idsTmp=0;
2378   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2380   if(!b)
2381     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2382   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2383   DataArrayInt *tmp0=0,*tmp1=0;
2384   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2385   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2386   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2389   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2390   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2391   //
2392   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2393   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2394   nodeIdsToDuplicate=s3.retn();
2395 }
2396
2397 /*!
2398  * This method operates a modification of the connectivity and coords in \b this.
2399  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2400  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2401  * 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
2402  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2403  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2404  * 
2405  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2406  * 
2407  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2408  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2409  */
2410 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2411 {
2412   int nbOfNodes=getNumberOfNodes();
2413   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2414   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2415 }
2416
2417 /*!
2418  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2419  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2420  * This method is a generalization of shiftNodeNumbersInConn().
2421  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2422  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2423  *         this->getNumberOfNodes(), in "Old to New" mode. 
2424  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2425  *  \throw If the nodal connectivity of cells is not defined.
2426  *
2427  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2428  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2429  */
2430 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2431 {
2432   checkConnectivityFullyDefined();
2433   int *conn=getNodalConnectivity()->getPointer();
2434   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2435   int nbOfCells=getNumberOfCells();
2436   for(int i=0;i<nbOfCells;i++)
2437     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2438       {
2439         int& node=conn[iconn];
2440         if(node>=0)//avoid polyhedron separator
2441           {
2442             node=newNodeNumbersO2N[node];
2443           }
2444       }
2445   _nodal_connec->declareAsNew();
2446   updateTime();
2447 }
2448
2449 /*!
2450  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2451  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2452  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2453  * 
2454  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2455  */
2456 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2457 {
2458   checkConnectivityFullyDefined();
2459   int *conn=getNodalConnectivity()->getPointer();
2460   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2461   int nbOfCells=getNumberOfCells();
2462   for(int i=0;i<nbOfCells;i++)
2463     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2464       {
2465         int& node=conn[iconn];
2466         if(node>=0)//avoid polyhedron separator
2467           {
2468             node+=delta;
2469           }
2470       }
2471   _nodal_connec->declareAsNew();
2472   updateTime();
2473 }
2474
2475 /*!
2476  * This method operates a modification of the connectivity in \b this.
2477  * 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.
2478  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2479  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2480  * 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
2481  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2482  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2483  * 
2484  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2485  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2486  * 
2487  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2488  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2489  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2490  */
2491 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2492 {
2493   checkConnectivityFullyDefined();
2494   std::map<int,int> m;
2495   int val=offset;
2496   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2497     m[*work]=val;
2498   int *conn=getNodalConnectivity()->getPointer();
2499   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2500   int nbOfCells=getNumberOfCells();
2501   for(int i=0;i<nbOfCells;i++)
2502     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2503       {
2504         int& node=conn[iconn];
2505         if(node>=0)//avoid polyhedron separator
2506           {
2507             std::map<int,int>::iterator it=m.find(node);
2508             if(it!=m.end())
2509               node=(*it).second;
2510           }
2511       }
2512   updateTime();
2513 }
2514
2515 /*!
2516  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2517  *
2518  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2519  * After the call of this method the number of cells remains the same as before.
2520  *
2521  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2522  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2523  * be strictly in [0;this->getNumberOfCells()).
2524  *
2525  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2526  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2527  * should be contained in[0;this->getNumberOfCells()).
2528  * 
2529  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2530  */
2531 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2532 {
2533   checkConnectivityFullyDefined();
2534   int nbCells=getNumberOfCells();
2535   const int *array=old2NewBg;
2536   if(check)
2537     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2538   //
2539   const int *conn=_nodal_connec->getConstPointer();
2540   const int *connI=_nodal_connec_index->getConstPointer();
2541   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2542   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2543   const int *n2oPtr=n2o->begin();
2544   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2545   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2546   newConn->copyStringInfoFrom(*_nodal_connec);
2547   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2548   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2549   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2550   //
2551   int *newC=newConn->getPointer();
2552   int *newCI=newConnI->getPointer();
2553   int loc=0;
2554   newCI[0]=loc;
2555   for(int i=0;i<nbCells;i++)
2556     {
2557       int pos=n2oPtr[i];
2558       int nbOfElts=connI[pos+1]-connI[pos];
2559       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2560       loc+=nbOfElts;
2561       newCI[i+1]=loc;
2562     }
2563   //
2564   setConnectivity(newConn,newConnI);
2565   if(check)
2566     free(const_cast<int *>(array));
2567 }
2568
2569 /*!
2570  * Finds cells whose bounding boxes intersect a given bounding box.
2571  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2572  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2573  *         zMax (if in 3D). 
2574  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2575  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2576  *         extent of the bounding box of cell to produce an addition to this bounding box.
2577  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2578  *         cells. The caller is to delete this array using decrRef() as it is no more
2579  *         needed. 
2580  *  \throw If the coordinates array is not set.
2581  *  \throw If the nodal connectivity of cells is not defined.
2582  *
2583  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2584  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2585  */
2586 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2587 {
2588   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2589   if(getMeshDimension()==-1)
2590     {
2591       elems->pushBackSilent(0);
2592       return elems.retn();
2593     }
2594   int dim=getSpaceDimension();
2595   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2596   const int* conn      = getNodalConnectivity()->getConstPointer();
2597   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2598   const double* coords = getCoords()->getConstPointer();
2599   int nbOfCells=getNumberOfCells();
2600   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2601     {
2602       for (int i=0; i<dim; i++)
2603         {
2604           elem_bb[i*2]=std::numeric_limits<double>::max();
2605           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2606         }
2607
2608       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2609         {
2610           int node= conn[inode];
2611           if(node>=0)//avoid polyhedron separator
2612             {
2613               for (int idim=0; idim<dim; idim++)
2614                 {
2615                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2616                     {
2617                       elem_bb[idim*2] = coords[node*dim+idim] ;
2618                     }
2619                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2620                     {
2621                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2622                     }
2623                 }
2624             }
2625         }
2626       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2627         elems->pushBackSilent(ielem);
2628     }
2629   return elems.retn();
2630 }
2631
2632 /*!
2633  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2634  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2635  * added in 'elems' parameter.
2636  */
2637 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2638 {
2639   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2640   if(getMeshDimension()==-1)
2641     {
2642       elems->pushBackSilent(0);
2643       return elems.retn();
2644     }
2645   int dim=getSpaceDimension();
2646   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2647   const int* conn      = getNodalConnectivity()->getConstPointer();
2648   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2649   const double* coords = getCoords()->getConstPointer();
2650   int nbOfCells=getNumberOfCells();
2651   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2652     {
2653       for (int i=0; i<dim; i++)
2654         {
2655           elem_bb[i*2]=std::numeric_limits<double>::max();
2656           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2657         }
2658
2659       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2660         {
2661           int node= conn[inode];
2662           if(node>=0)//avoid polyhedron separator
2663             {
2664               for (int idim=0; idim<dim; idim++)
2665                 {
2666                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2667                     {
2668                       elem_bb[idim*2] = coords[node*dim+idim] ;
2669                     }
2670                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2671                     {
2672                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2673                     }
2674                 }
2675             }
2676         }
2677       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2678         elems->pushBackSilent(ielem);
2679     }
2680   return elems.retn();
2681 }
2682
2683 /*!
2684  * Returns a type of a cell by its id.
2685  *  \param [in] cellId - the id of the cell of interest.
2686  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2687  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2688  */
2689 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2690 {
2691   const int *ptI=_nodal_connec_index->getConstPointer();
2692   const int *pt=_nodal_connec->getConstPointer();
2693   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2694     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2695   else
2696     {
2697       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2698       throw INTERP_KERNEL::Exception(oss.str().c_str());
2699     }
2700 }
2701
2702 /*!
2703  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2704  * This method does not throw exception if geometric type \a type is not in \a this.
2705  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2706  * The coordinates array is not considered here.
2707  *
2708  * \param [in] type the geometric type
2709  * \return cell ids in this having geometric type \a type.
2710  */
2711 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2712 {
2713   
2714   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2715   ret->alloc(0,1);
2716   checkConnectivityFullyDefined();
2717   int nbCells=getNumberOfCells();
2718   int mdim=getMeshDimension();
2719   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2720   if(mdim!=(int)cm.getDimension())
2721     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2722   const int *ptI=_nodal_connec_index->getConstPointer();
2723   const int *pt=_nodal_connec->getConstPointer();
2724   for(int i=0;i<nbCells;i++)
2725     {
2726       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2727         ret->pushBackSilent(i);
2728     }
2729   return ret.retn();
2730 }
2731
2732 /*!
2733  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2734  */
2735 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2736 {
2737   const int *ptI=_nodal_connec_index->getConstPointer();
2738   const int *pt=_nodal_connec->getConstPointer();
2739   int nbOfCells=getNumberOfCells();
2740   int ret=0;
2741   for(int i=0;i<nbOfCells;i++)
2742     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2743       ret++;
2744   return ret;
2745 }
2746
2747 /*!
2748  * Returns the nodal connectivity of a given cell.
2749  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2750  * all returned node ids can be used in getCoordinatesOfNode().
2751  *  \param [in] cellId - an id of the cell of interest.
2752  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2753  *         cleared before the appending.
2754  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2755  */
2756 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2757 {
2758   const int *ptI=_nodal_connec_index->getConstPointer();
2759   const int *pt=_nodal_connec->getConstPointer();
2760   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2761     if(*w>=0)
2762       conn.push_back(*w);
2763 }
2764
2765 std::string MEDCouplingUMesh::simpleRepr() const
2766 {
2767   static const char msg0[]="No coordinates specified !";
2768   std::ostringstream ret;
2769   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2770   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2771   int tmpp1,tmpp2;
2772   double tt=getTime(tmpp1,tmpp2);
2773   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2774   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2775   if(_mesh_dim>=-1)
2776     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2777   else
2778     { ret << " Mesh dimension has not been set or is invalid !"; }
2779   if(_coords!=0)
2780     {
2781       const int spaceDim=getSpaceDimension();
2782       ret << spaceDim << "\nInfo attached on space dimension : ";
2783       for(int i=0;i<spaceDim;i++)
2784         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2785       ret << "\n";
2786     }
2787   else
2788     ret << msg0 << "\n";
2789   ret << "Number of nodes : ";
2790   if(_coords!=0)
2791     ret << getNumberOfNodes() << "\n";
2792   else
2793     ret << msg0 << "\n";
2794   ret << "Number of cells : ";
2795   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2796     ret << getNumberOfCells() << "\n";
2797   else
2798     ret << "No connectivity specified !" << "\n";
2799   ret << "Cell types present : ";
2800   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2801     {
2802       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2803       ret << cm.getRepr() << " ";
2804     }
2805   ret << "\n";
2806   return ret.str();
2807 }
2808
2809 std::string MEDCouplingUMesh::advancedRepr() const
2810 {
2811   std::ostringstream ret;
2812   ret << simpleRepr();
2813   ret << "\nCoordinates array : \n___________________\n\n";
2814   if(_coords)
2815     _coords->reprWithoutNameStream(ret);
2816   else
2817     ret << "No array set !\n";
2818   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2819   reprConnectivityOfThisLL(ret);
2820   return ret.str();
2821 }
2822
2823 /*!
2824  * This method returns a C++ code that is a dump of \a this.
2825  * This method will throw if this is not fully defined.
2826  */
2827 std::string MEDCouplingUMesh::cppRepr() const
2828 {
2829   static const char coordsName[]="coords";
2830   static const char connName[]="conn";
2831   static const char connIName[]="connI";
2832   checkFullyDefined();
2833   std::ostringstream ret; ret << "// coordinates" << std::endl;
2834   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2835   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2836   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2837   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2838   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2839   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2840   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2841   return ret.str();
2842 }
2843
2844 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2845 {
2846   std::ostringstream ret;
2847   reprConnectivityOfThisLL(ret);
2848   return ret.str();
2849 }
2850
2851 /*!
2852  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2853  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2854  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2855  * some algos).
2856  * 
2857  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2858  * 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
2859  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2860  */
2861 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2862 {
2863   int mdim=getMeshDimension();
2864   if(mdim<0)
2865     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2866   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2867   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2868   bool needToCpyCT=true;
2869   if(!_nodal_connec)
2870     {
2871       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2872       needToCpyCT=false;
2873     }
2874   else
2875     {
2876       tmp1=_nodal_connec;
2877       tmp1->incrRef();
2878     }
2879   if(!_nodal_connec_index)
2880     {
2881       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2882       needToCpyCT=false;
2883     }
2884   else
2885     {
2886       tmp2=_nodal_connec_index;
2887       tmp2->incrRef();
2888     }
2889   ret->setConnectivity(tmp1,tmp2,false);
2890   if(needToCpyCT)
2891     ret->_types=_types;
2892   if(!_coords)
2893     {
2894       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2895       ret->setCoords(coords);
2896     }
2897   else
2898     ret->setCoords(_coords);
2899   return ret.retn();
2900 }
2901
2902 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2903 {
2904   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2905     {
2906       int nbOfCells=getNumberOfCells();
2907       const int *c=_nodal_connec->getConstPointer();
2908       const int *ci=_nodal_connec_index->getConstPointer();
2909       for(int i=0;i<nbOfCells;i++)
2910         {
2911           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2912           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2913           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2914           stream << "\n";
2915         }
2916     }
2917   else
2918     stream << "Connectivity not defined !\n";
2919 }
2920
2921 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2922 {
2923   const int *ptI=_nodal_connec_index->getConstPointer();
2924   const int *pt=_nodal_connec->getConstPointer();
2925   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2926     return ptI[cellId+1]-ptI[cellId]-1;
2927   else
2928     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2929 }
2930
2931 /*!
2932  * Returns types of cells of the specified part of \a this mesh.
2933  * This method avoids computing sub-mesh explicitely to get its types.
2934  *  \param [in] begin - an array of cell ids of interest.
2935  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2936  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2937  *         describing the cell types. 
2938  *  \throw If the coordinates array is not set.
2939  *  \throw If the nodal connectivity of cells is not defined.
2940  *  \sa getAllGeoTypes()
2941  */
2942 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2943 {
2944   checkFullyDefined();
2945   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2946   const int *conn=_nodal_connec->getConstPointer();
2947   const int *connIndex=_nodal_connec_index->getConstPointer();
2948   for(const int *w=begin;w!=end;w++)
2949     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2950   return ret;
2951 }
2952
2953 /*!
2954  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2955  * a set of types of cells constituting \a this mesh. 
2956  * This method is for advanced users having prepared their connectivity before. For
2957  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2958  *  \param [in] conn - the nodal connectivity array. 
2959  *  \param [in] connIndex - the nodal connectivity index array.
2960  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2961  *         mesh is updated.
2962  */
2963 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2964 {
2965   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2966   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2967   if(isComputingTypes)
2968     computeTypes();
2969   declareAsNew();
2970 }
2971
2972 /*!
2973  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2974  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2975  */
2976 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2977                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2978                                                                                 _types(other._types)
2979 {
2980   if(other._nodal_connec)
2981     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2982   if(other._nodal_connec_index)
2983     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2984 }
2985
2986 MEDCouplingUMesh::~MEDCouplingUMesh()
2987 {
2988   if(_nodal_connec)
2989     _nodal_connec->decrRef();
2990   if(_nodal_connec_index)
2991     _nodal_connec_index->decrRef();
2992 }
2993
2994 /*!
2995  * Recomputes a set of cell types of \a this mesh. For more info see
2996  * \ref MEDCouplingUMeshNodalConnectivity.
2997  */
2998 void MEDCouplingUMesh::computeTypes()
2999 {
3000   if(_nodal_connec && _nodal_connec_index)
3001     {
3002       _types.clear();
3003       const int *conn=_nodal_connec->getConstPointer();
3004       const int *connIndex=_nodal_connec_index->getConstPointer();
3005       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3006       if (nbOfElem > 0)
3007         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3008           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3009     }
3010 }
3011
3012 /*!
3013  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3014  */
3015 void MEDCouplingUMesh::checkFullyDefined() const
3016 {
3017   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3018     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3019 }
3020
3021 /*!
3022  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3023  */
3024 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3025 {
3026   if(!_nodal_connec_index || !_nodal_connec)
3027     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3028 }
3029
3030 /*!
3031  * Returns a number of cells constituting \a this mesh. 
3032  *  \return int - the number of cells in \a this mesh.
3033  *  \throw If the nodal connectivity of cells is not defined.
3034  */
3035 int MEDCouplingUMesh::getNumberOfCells() const
3036
3037   if(_nodal_connec_index)
3038     return _nodal_connec_index->getNumberOfTuples()-1;
3039   else
3040     if(_mesh_dim==-1)
3041       return 1;
3042     else
3043       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3044 }
3045
3046 /*!
3047  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3048  * mesh. For more info see \ref MEDCouplingMeshesPage.
3049  *  \return int - the dimension of \a this mesh.
3050  *  \throw If the mesh dimension is not defined using setMeshDimension().
3051  */
3052 int MEDCouplingUMesh::getMeshDimension() const
3053 {
3054   if(_mesh_dim<-1)
3055     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3056   return _mesh_dim;
3057 }
3058
3059 /*!
3060  * Returns a length of the nodal connectivity array.
3061  * This method is for test reason. Normally the integer returned is not useable by
3062  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3063  *  \return int - the length of the nodal connectivity array.
3064  */
3065 int MEDCouplingUMesh::getMeshLength() const
3066 {
3067   return _nodal_connec->getNbOfElems();
3068 }
3069
3070 /*!
3071  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3072  */
3073 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3074 {
3075   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3076   tinyInfo.push_back(getMeshDimension());
3077   tinyInfo.push_back(getNumberOfCells());
3078   if(_nodal_connec)
3079     tinyInfo.push_back(getMeshLength());
3080   else
3081     tinyInfo.push_back(-1);
3082 }
3083
3084 /*!
3085  * First step of unserialization process.
3086  */
3087 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3088 {
3089   return tinyInfo[6]<=0;
3090 }
3091
3092 /*!
3093  * Second step of serialization process.
3094  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3095  */
3096 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3097 {
3098   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3099   if(tinyInfo[5]!=-1)
3100     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3101 }
3102
3103 /*!
3104  * Third and final step of serialization process.
3105  */
3106 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3107 {
3108   MEDCouplingPointSet::serialize(a1,a2);
3109   if(getMeshDimension()>-1)
3110     {
3111       a1=DataArrayInt::New();
3112       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3113       int *ptA1=a1->getPointer();
3114       const int *conn=getNodalConnectivity()->getConstPointer();
3115       const int *index=getNodalConnectivityIndex()->getConstPointer();
3116       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3117       std::copy(conn,conn+getMeshLength(),ptA1);
3118     }
3119   else
3120     a1=0;
3121 }
3122
3123 /*!
3124  * Second and final unserialization process.
3125  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3126  */
3127 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3128 {
3129   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3130   setMeshDimension(tinyInfo[5]);
3131   if(tinyInfo[7]!=-1)
3132     {
3133       // Connectivity
3134       const int *recvBuffer=a1->getConstPointer();
3135       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3136       myConnecIndex->alloc(tinyInfo[6]+1,1);
3137       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3138       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3139       myConnec->alloc(tinyInfo[7],1);
3140       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3141       setConnectivity(myConnec, myConnecIndex);
3142     }
3143 }
3144
3145 /*!
3146  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3147  * CellIds are given using range specified by a start an end and step.
3148  */
3149 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3150 {
3151   checkFullyDefined();
3152   int ncell=getNumberOfCells();
3153   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3154   ret->_mesh_dim=_mesh_dim;
3155   ret->setCoords(_coords);
3156   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3157   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3158   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3159   int work=start;
3160   const int *conn=_nodal_connec->getConstPointer();
3161   const int *connIndex=_nodal_connec_index->getConstPointer();
3162   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3163     {
3164       if(work>=0 && work<ncell)
3165         {
3166           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3167         }
3168       else
3169         {
3170           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3171           throw INTERP_KERNEL::Exception(oss.str().c_str());
3172         }
3173     }
3174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3175   int *newConnPtr=newConn->getPointer();
3176   std::set<INTERP_KERNEL::NormalizedCellType> types;
3177   work=start;
3178   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3179     {
3180       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3181       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3182     }
3183   ret->setConnectivity(newConn,newConnI,false);
3184   ret->_types=types;
3185   ret->copyTinyInfoFrom(this);
3186   return ret.retn();
3187 }
3188
3189 /*!
3190  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3191  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3192  * The return newly allocated mesh will share the same coordinates as \a this.
3193  */
3194 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3195 {
3196   checkConnectivityFullyDefined();
3197   int ncell=getNumberOfCells();
3198   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3199   ret->_mesh_dim=_mesh_dim;
3200   ret->setCoords(_coords);
3201   std::size_t nbOfElemsRet=std::distance(begin,end);
3202   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3203   connIndexRet[0]=0;
3204   const int *conn=_nodal_connec->getConstPointer();
3205   const int *connIndex=_nodal_connec_index->getConstPointer();
3206   int newNbring=0;
3207   for(const int *work=begin;work!=end;work++,newNbring++)
3208     {
3209       if(*work>=0 && *work<ncell)
3210         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3211       else
3212         {
3213           free(connIndexRet);
3214           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3215           throw INTERP_KERNEL::Exception(oss.str().c_str());
3216         }
3217     }
3218   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3219   int *connRetWork=connRet;
3220   std::set<INTERP_KERNEL::NormalizedCellType> types;
3221   for(const int *work=begin;work!=end;work++)
3222     {
3223       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3224       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3225     }
3226   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3227   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3228   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3229   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3230   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3231   ret->_types=types;
3232   ret->copyTinyInfoFrom(this);
3233   return ret.retn();
3234 }
3235
3236 /*!
3237  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3238  * mesh.<br>
3239  * For 1D cells, the returned field contains lengths.<br>
3240  * For 2D cells, the returned field contains areas.<br>
3241  * For 3D cells, the returned field contains volumes.
3242  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3243  *         orientation, i.e. the volume is always positive.
3244  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3245  *         and one time . The caller is to delete this field using decrRef() as it is no
3246  *         more needed.
3247  */
3248 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3249 {
3250   std::string name="MeasureOfMesh_";
3251   name+=getName();
3252   int nbelem=getNumberOfCells();
3253   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3254   field->setName(name);
3255   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3256   array->alloc(nbelem,1);
3257   double *area_vol=array->getPointer();
3258   field->setArray(array) ; array=0;
3259   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3260   field->synchronizeTimeWithMesh();
3261   if(getMeshDimension()!=-1)
3262     {
3263       int ipt;
3264       INTERP_KERNEL::NormalizedCellType type;
3265       int dim_space=getSpaceDimension();
3266       const double *coords=getCoords()->getConstPointer();
3267       const int *connec=getNodalConnectivity()->getConstPointer();
3268       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3269       for(int iel=0;iel<nbelem;iel++)
3270         {
3271           ipt=connec_index[iel];
3272           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3273           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);
3274         }
3275       if(isAbs)
3276         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3277     }
3278   else
3279     {
3280       area_vol[0]=std::numeric_limits<double>::max();
3281     }
3282   return field.retn();
3283 }
3284
3285 /*!
3286  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3287  * mesh.<br>
3288  * For 1D cells, the returned array contains lengths.<br>
3289  * For 2D cells, the returned array contains areas.<br>
3290  * For 3D cells, the returned array contains volumes.
3291  * This method avoids building explicitly a part of \a this mesh to perform the work.
3292  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3293  *         orientation, i.e. the volume is always positive.
3294  *  \param [in] begin - an array of cell ids of interest.
3295  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3296  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3297  *          delete this array using decrRef() as it is no more needed.
3298  * 
3299  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3300  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3301  *  \sa getMeasureField()
3302  */
3303 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3304 {
3305   std::string name="PartMeasureOfMesh_";
3306   name+=getName();
3307   int nbelem=(int)std::distance(begin,end);
3308   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3309   array->setName(name);
3310   array->alloc(nbelem,1);
3311   double *area_vol=array->getPointer();
3312   if(getMeshDimension()!=-1)
3313     {
3314       int ipt;
3315       INTERP_KERNEL::NormalizedCellType type;
3316       int dim_space=getSpaceDimension();
3317       const double *coords=getCoords()->getConstPointer();
3318       const int *connec=getNodalConnectivity()->getConstPointer();
3319       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3320       for(const int *iel=begin;iel!=end;iel++)
3321         {
3322           ipt=connec_index[*iel];
3323           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3324           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3325         }
3326       if(isAbs)
3327         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3328     }
3329   else
3330     {
3331       area_vol[0]=std::numeric_limits<double>::max();
3332     }
3333   return array.retn();
3334 }
3335
3336 /*!
3337  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3338  * \a this one. The returned field contains the dual cell volume for each corresponding
3339  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3340  *  the dual mesh in P1 sens of \a this.<br>
3341  * For 1D cells, the returned field contains lengths.<br>
3342  * For 2D cells, the returned field contains areas.<br>
3343  * For 3D cells, the returned field contains volumes.
3344  * This method is useful to check "P1*" conservative interpolators.
3345  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3346  *         orientation, i.e. the volume is always positive.
3347  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3348  *          nodes and one time. The caller is to delete this array using decrRef() as
3349  *          it is no more needed.
3350  */
3351 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3352 {
3353   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3354   std::string name="MeasureOnNodeOfMesh_";
3355   name+=getName();
3356   int nbNodes=getNumberOfNodes();
3357   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3358   double cst=1./((double)getMeshDimension()+1.);
3359   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3360   array->alloc(nbNodes,1);
3361   double *valsToFill=array->getPointer();
3362   std::fill(valsToFill,valsToFill+nbNodes,0.);
3363   const double *values=tmp->getArray()->getConstPointer();
3364   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3366   getReverseNodalConnectivity(da,daInd);
3367   const int *daPtr=da->getConstPointer();
3368   const int *daIPtr=daInd->getConstPointer();
3369   for(int i=0;i<nbNodes;i++)
3370     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3371       valsToFill[i]+=cst*values[*cell];
3372   ret->setMesh(this);
3373   ret->setArray(array);
3374   return ret.retn();
3375 }
3376
3377 /*!
3378  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3379  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3380  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3381  * and are normalized.
3382  * <br> \a this can be either 
3383  * - a  2D mesh in 2D or 3D space or 
3384  * - an 1D mesh in 2D space.
3385  * 
3386  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3387  *          cells and one time. The caller is to delete this field using decrRef() as
3388  *          it is no more needed.
3389  *  \throw If the nodal connectivity of cells is not defined.
3390  *  \throw If the coordinates array is not set.
3391  *  \throw If the mesh dimension is not set.
3392  *  \throw If the mesh and space dimension is not as specified above.
3393  */
3394 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3395 {
3396   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3397     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3398   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3399   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3400   int nbOfCells=getNumberOfCells();
3401   int nbComp=getMeshDimension()+1;
3402   array->alloc(nbOfCells,nbComp);
3403   double *vals=array->getPointer();
3404   const int *connI=_nodal_connec_index->getConstPointer();
3405   const int *conn=_nodal_connec->getConstPointer();
3406   const double *coords=_coords->getConstPointer();
3407   if(getMeshDimension()==2)
3408     {
3409       if(getSpaceDimension()==3)
3410         {
3411           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3412           const double *locPtr=loc->getConstPointer();
3413           for(int i=0;i<nbOfCells;i++,vals+=3)
3414             {
3415               int offset=connI[i];
3416               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3417               double n=INTERP_KERNEL::norm<3>(vals);
3418               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3419             }
3420         }
3421       else
3422         {
3423           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3424           const double *isAbsPtr=isAbs->getArray()->begin();
3425           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3426             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3427         }
3428     }
3429   else//meshdimension==1
3430     {
3431       double tmp[2];
3432       for(int i=0;i<nbOfCells;i++)
3433         {
3434           int offset=connI[i];
3435           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3436           double n=INTERP_KERNEL::norm<2>(tmp);
3437           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3438           *vals++=-tmp[1];
3439           *vals++=tmp[0];
3440         }
3441     }
3442   ret->setArray(array);
3443   ret->setMesh(this);
3444   ret->synchronizeTimeWithSupport();
3445   return ret.retn();
3446 }
3447
3448 /*!
3449  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3450  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3451  * and are normalized.
3452  * <br> \a this can be either 
3453  * - a  2D mesh in 2D or 3D space or 
3454  * - an 1D mesh in 2D space.
3455  * 
3456  * This method avoids building explicitly a part of \a this mesh to perform the work.
3457  *  \param [in] begin - an array of cell ids of interest.
3458  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3459  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3460  *          cells and one time. The caller is to delete this field using decrRef() as
3461  *          it is no more needed.
3462  *  \throw If the nodal connectivity of cells is not defined.
3463  *  \throw If the coordinates array is not set.
3464  *  \throw If the mesh dimension is not set.
3465  *  \throw If the mesh and space dimension is not as specified above.
3466  *  \sa buildOrthogonalField()
3467  *
3468  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3469  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3470  */
3471 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3472 {
3473   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3474     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3475   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3476   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3477   std::size_t nbelems=std::distance(begin,end);
3478   int nbComp=getMeshDimension()+1;
3479   array->alloc((int)nbelems,nbComp);
3480   double *vals=array->getPointer();
3481   const int *connI=_nodal_connec_index->getConstPointer();
3482   const int *conn=_nodal_connec->getConstPointer();
3483   const double *coords=_coords->getConstPointer();
3484   if(getMeshDimension()==2)
3485     {
3486       if(getSpaceDimension()==3)
3487         {
3488           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3489           const double *locPtr=loc->getConstPointer();
3490           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3491             {
3492               int offset=connI[*i];
3493               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3494               double n=INTERP_KERNEL::norm<3>(vals);
3495               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3496             }
3497         }
3498       else
3499         {
3500           for(std::size_t i=0;i<nbelems;i++)
3501             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3502         }
3503     }
3504   else//meshdimension==1
3505     {
3506       double tmp[2];
3507       for(const int *i=begin;i!=end;i++)
3508         {
3509           int offset=connI[*i];
3510           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3511           double n=INTERP_KERNEL::norm<2>(tmp);
3512           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3513           *vals++=-tmp[1];
3514           *vals++=tmp[0];
3515         }
3516     }
3517   ret->setArray(array);
3518   ret->setMesh(this);
3519   ret->synchronizeTimeWithSupport();
3520   return ret.retn();
3521 }
3522
3523 /*!
3524  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3525  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3526  * and are \b not normalized.
3527  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3528  *          cells and one time. The caller is to delete this field using decrRef() as
3529  *          it is no more needed.
3530  *  \throw If the nodal connectivity of cells is not defined.
3531  *  \throw If the coordinates array is not set.
3532  *  \throw If \a this->getMeshDimension() != 1.
3533  *  \throw If \a this mesh includes cells of type other than SEG2.
3534  */
3535 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3536 {
3537    if(getMeshDimension()!=1)
3538     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3539    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3540      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3541    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3542    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3543    int nbOfCells=getNumberOfCells();
3544    int spaceDim=getSpaceDimension();
3545    array->alloc(nbOfCells,spaceDim);
3546    double *pt=array->getPointer();
3547    const double *coo=getCoords()->getConstPointer();
3548    std::vector<int> conn;
3549    conn.reserve(2);
3550    for(int i=0;i<nbOfCells;i++)
3551      {
3552        conn.resize(0);
3553        getNodeIdsOfCell(i,conn);
3554        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3555      }
3556    ret->setArray(array);
3557    ret->setMesh(this);
3558    ret->synchronizeTimeWithSupport();
3559    return ret.retn();   
3560 }
3561
3562 /*!
3563  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3564  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3565  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3566  * from. If a result face is shared by two 3D cells, then the face in included twice in
3567  * the result mesh.
3568  *  \param [in] origin - 3 components of a point defining location of the plane.
3569  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3570  *         must be greater than 1e-6.
3571  *  \param [in] eps - half-thickness of the plane.
3572  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3573  *         producing correspondent 2D cells. The caller is to delete this array
3574  *         using decrRef() as it is no more needed.
3575  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3576  *         not share the node coordinates array with \a this mesh. The caller is to
3577  *         delete this mesh using decrRef() as it is no more needed.  
3578  *  \throw If the coordinates array is not set.
3579  *  \throw If the nodal connectivity of cells is not defined.
3580  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3581  *  \throw If magnitude of \a vec is less than 1e-6.
3582  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3583  *  \throw If \a this includes quadratic cells.
3584  */
3585 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3586 {
3587   checkFullyDefined();
3588   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3589     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3590   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3591   if(candidates->empty())
3592     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3593   std::vector<int> nodes;
3594   DataArrayInt *cellIds1D=0;
3595   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3596   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3597   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3598   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3599   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3600   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3601   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3602   revDesc2=0; revDescIndx2=0;
3603   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3604   revDesc1=0; revDescIndx1=0;
3605   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3606   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3607   //
3608   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3609   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3610     cut3DCurve[*it]=-1;
3611   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3612   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3613   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3614                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3615                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3616   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3617   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3618   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3619   if(cellIds2->empty())
3620     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3621   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3622   ret->setCoords(mDesc1->getCoords());
3623   ret->setConnectivity(conn,connI,true);
3624   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3625   return ret.retn();
3626 }
3627
3628 /*!
3629  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3630 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
3631 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3632 the result mesh.
3633  *  \param [in] origin - 3 components of a point defining location of the plane.
3634  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3635  *         must be greater than 1e-6.
3636  *  \param [in] eps - half-thickness of the plane.
3637  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3638  *         producing correspondent segments. The caller is to delete this array
3639  *         using decrRef() as it is no more needed.
3640  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3641  *         mesh in 3D space. This mesh does not share the node coordinates array with
3642  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3643  *         no more needed. 
3644  *  \throw If the coordinates array is not set.
3645  *  \throw If the nodal connectivity of cells is not defined.
3646  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3647  *  \throw If magnitude of \a vec is less than 1e-6.
3648  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3649  *  \throw If \a this includes quadratic cells.
3650  */
3651 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3652 {
3653   checkFullyDefined();
3654   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3655     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3656   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3657   if(candidates->empty())
3658     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3659   std::vector<int> nodes;
3660   DataArrayInt *cellIds1D=0;
3661   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3662   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3663   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3664   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3665   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3666   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3667   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3668   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3669   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3670   //
3671   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3672   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3673     cut3DCurve[*it]=-1;
3674   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3675   int ncellsSub=subMesh->getNumberOfCells();
3676   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3677   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3678                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3679                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3680   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3681   conn->alloc(0,1);
3682   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3683   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3684   for(int i=0;i<ncellsSub;i++)
3685     {
3686       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3687         {
3688           if(cut3DSurf[i].first!=-2)
3689             {
3690               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3691               connI->pushBackSilent(conn->getNumberOfTuples());
3692               cellIds2->pushBackSilent(i);
3693             }
3694           else
3695             {
3696               int cellId3DSurf=cut3DSurf[i].second;
3697               int offset=nodalI[cellId3DSurf]+1;
3698               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3699               for(int j=0;j<nbOfEdges;j++)
3700                 {
3701                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3702                   connI->pushBackSilent(conn->getNumberOfTuples());
3703                   cellIds2->pushBackSilent(cellId3DSurf);
3704                 }
3705             }
3706         }
3707     }
3708   if(cellIds2->empty())
3709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3710   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3711   ret->setCoords(mDesc1->getCoords());
3712   ret->setConnectivity(conn,connI,true);
3713   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3714   return ret.retn();
3715 }
3716
3717 /*!
3718  * Finds cells whose bounding boxes intersect a given plane.
3719  *  \param [in] origin - 3 components of a point defining location of the plane.
3720  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3721  *         must be greater than 1e-6.
3722  *  \param [in] eps - half-thickness of the plane.
3723  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3724  *         cells. The caller is to delete this array using decrRef() as it is no more
3725  *         needed.
3726  *  \throw If the coordinates array is not set.
3727  *  \throw If the nodal connectivity of cells is not defined.
3728  *  \throw If \a this->getSpaceDimension() != 3.
3729  *  \throw If magnitude of \a vec is less than 1e-6.
3730  *  \sa buildSlice3D()
3731  */
3732 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3733 {
3734   checkFullyDefined();
3735   if(getSpaceDimension()!=3)
3736     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3737   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3738   if(normm<1e-6)
3739     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3740   double vec2[3];
3741   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3742   double angle=acos(vec[2]/normm);
3743   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3744   double bbox[6];
3745   if(angle>eps)
3746     {
3747       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3748       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3749       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3750       mw->setCoords(coo);
3751       mw->getBoundingBox(bbox);
3752       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3753       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3754     }
3755   else
3756     {
3757       getBoundingBox(bbox);
3758       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3759       cellIds=getCellsInBoundingBox(bbox,eps);
3760     }
3761   return cellIds.retn();
3762 }
3763
3764 /*!
3765  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3766  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3767  * No consideration of coordinate is done by this method.
3768  * 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)
3769  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3770  */
3771 bool MEDCouplingUMesh::isContiguous1D() const
3772 {
3773   if(getMeshDimension()!=1)
3774     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3775   int nbCells=getNumberOfCells();
3776   if(nbCells<1)
3777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3778   const int *connI=_nodal_connec_index->getConstPointer();
3779   const int *conn=_nodal_connec->getConstPointer();
3780   int ref=conn[connI[0]+2];
3781   for(int i=1;i<nbCells;i++)
3782     {
3783       if(conn[connI[i]+1]!=ref)
3784         return false;
3785       ref=conn[connI[i]+2];
3786     }
3787   return true;
3788 }
3789
3790 /*!
3791  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3792  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3793  * \param pt reference point of the line
3794  * \param v normalized director vector of the line
3795  * \param eps max precision before throwing an exception
3796  * \param res output of size this->getNumberOfCells
3797  */
3798 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3799 {
3800   if(getMeshDimension()!=1)
3801     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3802    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3803      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3804    if(getSpaceDimension()!=3)
3805      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3806    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3807    const double *fPtr=f->getArray()->getConstPointer();
3808    double tmp[3];
3809    for(int i=0;i<getNumberOfCells();i++)
3810      {
3811        const double *tmp1=fPtr+3*i;
3812        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3813        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3814        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3815        double n1=INTERP_KERNEL::norm<3>(tmp);
3816        n1/=INTERP_KERNEL::norm<3>(tmp1);
3817        if(n1>eps)
3818          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3819      }
3820    const double *coo=getCoords()->getConstPointer();
3821    for(int i=0;i<getNumberOfNodes();i++)
3822      {
3823        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3824        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3825        res[i]=std::accumulate(tmp,tmp+3,0.);
3826      }
3827 }
3828
3829 /*!
3830  * 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. 
3831  * \a this is expected to be a mesh so that its space dimension is equal to its
3832  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3833  * 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).
3834  
3835  * 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
3836  * 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).
3837  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3838  *
3839  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3840  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3841  *
3842  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3843  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3844  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3845  * \return the positive value of the distance.
3846  * \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
3847  * dimension - 1.
3848  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3849  */
3850 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3851 {
3852   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3853   if(meshDim!=spaceDim-1)
3854     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3855   if(meshDim!=2 && meshDim!=1)
3856     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3857   checkFullyDefined();
3858   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3859     { 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()); }
3860   DataArrayInt *ret1=0;
3861   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3862   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3863   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3864   cellId=*ret1Safe->begin();
3865   return *ret0->begin();
3866 }
3867
3868 /*!
3869  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3870  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3871  * 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
3872  * 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).
3873  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3874  * 
3875  * \a this is expected to be a mesh so that its space dimension is equal to its
3876  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3877  * 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).
3878  *
3879  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3880  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3881  *
3882  * \param [in] pts the list of points in which each tuple represents a point
3883  * \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.
3884  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3885  * \throw if number of components of \a pts is not equal to the space dimension.
3886  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3887  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3888  */
3889 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3890 {
3891   if(!pts)
3892     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3893   pts->checkAllocated();
3894   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3895   if(meshDim!=spaceDim-1)
3896     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3897   if(meshDim!=2 && meshDim!=1)
3898     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3899   if(pts->getNumberOfComponents()!=spaceDim)
3900     {
3901       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3902       throw INTERP_KERNEL::Exception(oss.str().c_str());
3903     }
3904   checkFullyDefined();
3905   int nbCells=getNumberOfCells();
3906   if(nbCells==0)
3907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3908   int nbOfPts=pts->getNumberOfTuples();
3909   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3910   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3911   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3912   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3913   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3914   const double *bbox(bboxArr->begin());
3915   switch(spaceDim)
3916     {
3917     case 3:
3918       {
3919         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3920         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3921           {
3922             double x=std::numeric_limits<double>::max();
3923             std::vector<int> elems;
3924             myTree.getMinDistanceOfMax(ptsPtr,x);
3925             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3926             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3927           }
3928         break;
3929       }
3930     case 2:
3931       {
3932         BBTreeDst<2> myTree(bbox,0,0,nbCells);
3933         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3934           {
3935             double x=std::numeric_limits<double>::max();
3936             std::vector<int> elems;
3937             myTree.getMinDistanceOfMax(ptsPtr,x);
3938             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3939             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3940           }
3941         break;
3942       }
3943     default:
3944       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3945     }
3946   cellIds=ret1.retn();
3947   return ret0.retn();
3948 }
3949
3950 /*!
3951  * \param [in] pt the start pointer (included) of the coordinates of the point
3952  * \param [in] cellIdsBg the start pointer (included) of cellIds
3953  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3954  * \param [in] nc nodal connectivity
3955  * \param [in] ncI nodal connectivity index
3956  * \param [in,out] ret0 the min distance between \a this and the external input point
3957  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3958  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3959  */
3960 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)
3961 {
3962   cellId=-1;
3963   ret0=std::numeric_limits<double>::max();
3964   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3965     {
3966       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3967         {
3968         case INTERP_KERNEL::NORM_TRI3:
3969           {
3970             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3971             if(tmp<ret0)
3972               { ret0=tmp; cellId=*zeCell; }
3973             break;
3974           }
3975         case INTERP_KERNEL::NORM_QUAD4:
3976         case INTERP_KERNEL::NORM_POLYGON:
3977           {
3978             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3979             if(tmp<ret0)
3980               { ret0=tmp; cellId=*zeCell; }
3981             break;
3982           }
3983         default:
3984           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3985         }
3986     }
3987 }
3988
3989 /*!
3990  * \param [in] pt the start pointer (included) of the coordinates of the point
3991  * \param [in] cellIdsBg the start pointer (included) of cellIds
3992  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3993  * \param [in] nc nodal connectivity
3994  * \param [in] ncI nodal connectivity index
3995  * \param [in,out] ret0 the min distance between \a this and the external input point
3996  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3997  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3998  */
3999 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)
4000 {
4001   cellId=-1;
4002   ret0=std::numeric_limits<double>::max();
4003   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4004     {
4005        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4006         {
4007         case INTERP_KERNEL::NORM_SEG2:
4008           {
4009             std::size_t uselessEntry=0;
4010             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4011             tmp=sqrt(tmp);
4012             if(tmp<ret0)
4013               { ret0=tmp; cellId=*zeCell; }
4014             break;
4015           }
4016         default:
4017           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4018         }
4019     }
4020 }
4021
4022 /*!
4023  * Finds cells in contact with a ball (i.e. a point with precision). 
4024  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4025  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4026  *
4027  * \warning This method is suitable if the caller intends to evaluate only one
4028  *          point, for more points getCellsContainingPoints() is recommended as it is
4029  *          faster. 
4030  *  \param [in] pos - array of coordinates of the ball central point.
4031  *  \param [in] eps - ball radius.
4032  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4033  *         if there are no such cells.
4034  *  \throw If the coordinates array is not set.
4035  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4036  */
4037 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4038 {
4039   std::vector<int> elts;
4040   getCellsContainingPoint(pos,eps,elts);
4041   if(elts.empty())
4042     return -1;
4043   return elts.front();
4044 }
4045
4046 /*!
4047  * Finds cells in contact with a ball (i.e. a point with precision).
4048  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4049  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4050  * \warning This method is suitable if the caller intends to evaluate only one
4051  *          point, for more points getCellsContainingPoints() is recommended as it is
4052  *          faster. 
4053  *  \param [in] pos - array of coordinates of the ball central point.
4054  *  \param [in] eps - ball radius.
4055  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4056  *         before inserting ids.
4057  *  \throw If the coordinates array is not set.
4058  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4059  *
4060  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4061  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4062  */
4063 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4064 {
4065   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4066   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4067   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4068 }
4069
4070 /// @cond INTERNAL
4071
4072 namespace ParaMEDMEM
4073 {
4074   template<const int SPACEDIMM>
4075   class DummyClsMCUG
4076   {
4077   public:
4078     static const int MY_SPACEDIM=SPACEDIMM;
4079     static const int MY_MESHDIM=8;
4080     typedef int MyConnType;
4081     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4082     // begin
4083     // useless, but for windows compilation ...
4084     const double* getCoordinatesPtr() const { return 0; }
4085     const int* getConnectivityPtr() const { return 0; }
4086     const int* getConnectivityIndexPtr() const { return 0; }
4087     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4088     // end
4089   };
4090
4091   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4092   {
4093     INTERP_KERNEL::Edge *ret=0;
4094     switch(typ)
4095       {
4096       case INTERP_KERNEL::NORM_SEG2:
4097         {
4098           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4099           break;
4100         }
4101       case INTERP_KERNEL::NORM_SEG3:
4102         {
4103           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4104           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4105           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4106           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4107           bool colinearity=inters.areColinears();
4108           delete e1; delete e2;
4109           if(colinearity)
4110             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4111           else
4112             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4113           mapp2[bg[2]].second=false;
4114           break;
4115         }
4116       default:
4117         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4118       }
4119     return ret;
4120   }
4121
4122   /*!
4123    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4124    * the global mesh 'mDesc'.
4125    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4126    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4127    */
4128   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4129       std::map<INTERP_KERNEL::Node *,int>& mapp)
4130       throw(INTERP_KERNEL::Exception)
4131   {
4132     mapp.clear();
4133     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.
4134     const double *coo=mDesc->getCoords()->getConstPointer();
4135     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4136     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4137     std::set<int> s;
4138     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4139       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4140     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4141       {
4142         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4143         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4144       }
4145     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4146     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4147       {
4148         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4149         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4150       }
4151     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4152       {
4153         if((*it2).second.second)
4154           mapp[(*it2).second.first]=(*it2).first;
4155         ((*it2).second.first)->decrRef();
4156       }
4157     return ret;
4158   }
4159
4160   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4161   {
4162     if(nodeId>=offset2)
4163       {
4164         int locId=nodeId-offset2;
4165         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4166       }
4167     if(nodeId>=offset1)
4168       {
4169         int locId=nodeId-offset1;
4170         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4171       }
4172     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4173   }
4174
4175   /**
4176    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4177    */
4178   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4179                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4180                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4181   {
4182     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4183       {
4184         int eltId1=abs(*desc1)-1;
4185         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4186           {
4187             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4188             if(it==mappRev.end())
4189               {
4190                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4191                 mapp[node]=*it1;
4192                 mappRev[*it1]=node;
4193               }
4194           }
4195       }
4196   }
4197 }
4198
4199 /// @endcond
4200
4201 template<int SPACEDIM>
4202 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4203                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4204 {
4205   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4206   int *eltsIndexPtr(eltsIndex->getPointer());
4207   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4208   const double *bbox(bboxArr->begin());
4209   int nbOfCells=getNumberOfCells();
4210   const int *conn=_nodal_connec->getConstPointer();
4211   const int *connI=_nodal_connec_index->getConstPointer();
4212   double bb[2*SPACEDIM];
4213   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4214   for(int i=0;i<nbOfPoints;i++)
4215     {
4216       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4217       for(int j=0;j<SPACEDIM;j++)
4218         {
4219           bb[2*j]=pos[SPACEDIM*i+j];
4220           bb[2*j+1]=pos[SPACEDIM*i+j];
4221         }
4222       std::vector<int> candidates;
4223       myTree.getIntersectingElems(bb,candidates);
4224       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4225         {
4226           int sz(connI[(*iter)+1]-connI[*iter]-1);
4227           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4228           bool status(false);
4229           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4230             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4231           else
4232             {
4233               if(SPACEDIM!=2)
4234                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4235               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4236               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4237               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4238               INTERP_KERNEL::QuadraticPolygon *pol(0);
4239               for(int j=0;j<sz;j++)
4240                 {
4241                   int nodeId(conn[connI[*iter]+1+j]);
4242                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4243                 }
4244               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4245                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4246               else
4247                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4248               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4249               double a(0.),b(0.),c(0.);
4250               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4251               status=pol->isInOrOut2(n);
4252               delete pol; n->decrRef();
4253             }
4254           if(status)
4255             {
4256               eltsIndexPtr[i+1]++;
4257               elts->pushBackSilent(*iter);
4258             }
4259         }
4260     }
4261 }
4262 /*!
4263  * Finds cells in contact with several balls (i.e. points with precision).
4264  * This method is an extension of getCellContainingPoint() and
4265  * getCellsContainingPoint() for the case of multiple points.
4266  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4267  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4268  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4269  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4270  *         this->getSpaceDimension() * \a nbOfPoints 
4271  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4272  *  \param [in] eps - radius of balls (i.e. the precision).
4273  *  \param [out] elts - vector returning ids of found cells.
4274  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4275  *         dividing cell ids in \a elts into groups each referring to one
4276  *         point. Its every element (except the last one) is an index pointing to the
4277  *         first id of a group of cells. For example cells in contact with the *i*-th
4278  *         point are described by following range of indices:
4279  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4280  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4281  *         Number of cells in contact with the *i*-th point is
4282  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4283  *  \throw If the coordinates array is not set.
4284  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4285  *
4286  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4287  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4288  */
4289 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4290                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4291 {
4292   int spaceDim=getSpaceDimension();
4293   int mDim=getMeshDimension();
4294   if(spaceDim==3)
4295     {
4296       if(mDim==3)
4297         {
4298           const double *coords=_coords->getConstPointer();
4299           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4300         }
4301       /*else if(mDim==2)
4302         {
4303           
4304         }*/
4305       else
4306         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4307     }
4308   else if(spaceDim==2)
4309     {
4310       if(mDim==2)
4311         {
4312           const double *coords=_coords->getConstPointer();
4313           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4314         }
4315       else
4316         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4317     }
4318   else if(spaceDim==1)
4319     {
4320       if(mDim==1)
4321         {
4322           const double *coords=_coords->getConstPointer();
4323           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4324         }
4325       else
4326         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4327     }
4328   else
4329     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4330 }
4331
4332 /*!
4333  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4334  * least two its edges intersect each other anywhere except their extremities. An
4335  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4336  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4337  *         cleared before filling in.
4338  *  \param [in] eps - precision.
4339  *  \throw If \a this->getMeshDimension() != 2.
4340  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4341  */
4342 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4343 {
4344   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4345   if(getMeshDimension()!=2)
4346     throw INTERP_KERNEL::Exception(msg);
4347   int spaceDim=getSpaceDimension();
4348   if(spaceDim!=2 && spaceDim!=3)
4349     throw INTERP_KERNEL::Exception(msg);
4350   const int *conn=_nodal_connec->getConstPointer();
4351   const int *connI=_nodal_connec_index->getConstPointer();
4352   int nbOfCells=getNumberOfCells();
4353   std::vector<double> cell2DinS2;
4354   for(int i=0;i<nbOfCells;i++)
4355     {
4356       int offset=connI[i];
4357       int nbOfNodesForCell=connI[i+1]-offset-1;
4358       if(nbOfNodesForCell<=3)
4359         continue;
4360       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4361       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4362       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4363         cells.push_back(i);
4364       cell2DinS2.clear();
4365     }
4366 }
4367
4368 /*!
4369  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4370  *
4371  * 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.
4372  * 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.
4373  * 
4374  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4375  * This convex envelop is computed using Jarvis march algorithm.
4376  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4377  * 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)
4378  * 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.
4379  *
4380  * \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.
4381  */
4382 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4383 {
4384   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4385     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4386   checkFullyDefined();
4387   const double *coords=getCoords()->getConstPointer();
4388   int nbOfCells=getNumberOfCells();
4389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4390   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4392   int *workIndexOut=nodalConnecIndexOut->getPointer();
4393   *workIndexOut=0;
4394   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4395   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4396   std::set<INTERP_KERNEL::NormalizedCellType> types;
4397   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4398   isChanged->alloc(0,1);
4399   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4400     {
4401       int pos=nodalConnecOut->getNumberOfTuples();
4402       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4403         isChanged->pushBackSilent(i);
4404       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4405       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4406     }
4407   if(isChanged->empty())
4408     return 0;
4409   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4410   _types=types;
4411   return isChanged.retn();
4412 }
4413
4414 /*!
4415  * This method is \b NOT const because it can modify \a this.
4416  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4417  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4418  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4419  * \b 1 for translation and rotation around point of 'mesh1D'.
4420  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4421  */
4422 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4423 {
4424   checkFullyDefined();
4425   mesh1D->checkFullyDefined();
4426   if(!mesh1D->isContiguous1D())
4427     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4428   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4429     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4430   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4431     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4432   if(mesh1D->getMeshDimension()!=1)
4433     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4434   bool isQuad=false;
4435   if(isPresenceOfQuadratic())
4436     {
4437       if(mesh1D->isFullyQuadratic())
4438         isQuad=true;
4439       else
4440         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4441     }
4442   zipCoords();
4443   int oldNbOfNodes=getNumberOfNodes();
4444   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4445   switch(policy)
4446     {
4447     case 0:
4448       {
4449         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4450         break;
4451       }
4452     case 1:
4453       {
4454         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4455         break;
4456       }
4457     default:
4458       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4459     }
4460   setCoords(newCoords);
4461   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4462   updateTime();
4463   return ret.retn();
4464 }
4465
4466 /*!
4467  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4468  * If it is not the case an exception will be thrown.
4469  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4470  * intersection of plane defined by ('origin','vec').
4471  * This method has one in/out parameter : 'cut3DCurve'.
4472  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4473  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4474  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4475  * This method will throw an exception if \a this contains a non linear segment.
4476  */
4477 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4478 {
4479   checkFullyDefined();
4480   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4481     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4482   int ncells=getNumberOfCells();
4483   int nnodes=getNumberOfNodes();
4484   double vec2[3],vec3[3],vec4[3];
4485   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4486   if(normm<1e-6)
4487     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4488   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4489   const int *conn=_nodal_connec->getConstPointer();
4490   const int *connI=_nodal_connec_index->getConstPointer();
4491   const double *coo=_coords->getConstPointer();
4492   std::vector<double> addCoo;
4493   for(int i=0;i<ncells;i++)
4494     {
4495       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4496         {
4497           if(cut3DCurve[i]==-2)
4498             {
4499               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4500               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];
4501               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4502               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4503               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4504                 {
4505                   const double *st2=coo+3*st;
4506                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4507                   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]));
4508                   if(pos>eps && pos<1-eps)
4509                     {
4510                       int nNode=((int)addCoo.size())/3;
4511                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4512                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4513                       cut3DCurve[i]=nnodes+nNode;
4514                     }
4515                 }
4516             }
4517         }
4518       else
4519         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4520     }
4521   if(!addCoo.empty())
4522     {
4523       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4524       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4525       coo2->alloc(newNbOfNodes,3);
4526       double *tmp=coo2->getPointer();
4527       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4528       std::copy(addCoo.begin(),addCoo.end(),tmp);
4529       DataArrayDouble::SetArrayIn(coo2,_coords);
4530     }
4531 }
4532
4533 /*!
4534  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4535  * \param mesh1D is the input 1D mesh used for translation computation.
4536  * \return newCoords new coords filled by this method. 
4537  */
4538 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4539 {
4540   int oldNbOfNodes=getNumberOfNodes();
4541   int nbOf1DCells=mesh1D->getNumberOfCells();
4542   int spaceDim=getSpaceDimension();
4543   DataArrayDouble *ret=DataArrayDouble::New();
4544   std::vector<bool> isQuads;
4545   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4546   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4547   double *retPtr=ret->getPointer();
4548   const double *coords=getCoords()->getConstPointer();
4549   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4550   std::vector<int> v;
4551   std::vector<double> c;
4552   double vec[3];
4553   v.reserve(3);
4554   c.reserve(6);
4555   for(int i=0;i<nbOf1DCells;i++)
4556     {
4557       v.resize(0);
4558       mesh1D->getNodeIdsOfCell(i,v);
4559       c.resize(0);
4560       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4561       mesh1D->getCoordinatesOfNode(v[0],c);
4562       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4563       for(int j=0;j<oldNbOfNodes;j++)
4564         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4565       if(isQuad)
4566         {
4567           c.resize(0);
4568           mesh1D->getCoordinatesOfNode(v[1],c);
4569           mesh1D->getCoordinatesOfNode(v[0],c);
4570           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4571           for(int j=0;j<oldNbOfNodes;j++)
4572             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4573         }
4574     }
4575   ret->copyStringInfoFrom(*getCoords());
4576   return ret;
4577 }
4578
4579 /*!
4580  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4581  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4582  * \return newCoords new coords filled by this method. 
4583  */
4584 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4585 {
4586   if(mesh1D->getSpaceDimension()==2)
4587     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4588   if(mesh1D->getSpaceDimension()==3)
4589     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4590   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4591 }
4592
4593 /*!
4594  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4595  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4596  * \return newCoords new coords filled by this method. 
4597  */
4598 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4599 {
4600   if(isQuad)
4601     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4602   int oldNbOfNodes=getNumberOfNodes();
4603   int nbOf1DCells=mesh1D->getNumberOfCells();
4604   if(nbOf1DCells<2)
4605     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4606   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4607   int nbOfLevsInVec=nbOf1DCells+1;
4608   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4609   double *retPtr=ret->getPointer();
4610   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4611   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4612   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4613   tmp->setCoords(tmp2);
4614   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4615   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4616   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4617   for(int i=1;i<nbOfLevsInVec;i++)
4618     {
4619       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4620       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4621       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4622       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4623       tmp->translate(vec);
4624       double tmp3[2],radius,alpha,alpha0;
4625       const double *p0=i+1<nbOfLevsInVec?begin:third;
4626       const double *p1=i+1<nbOfLevsInVec?end:begin;
4627       const double *p2=i+1<nbOfLevsInVec?third:end;
4628       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4629       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]);
4630       double angle=acos(cosangle/(radius*radius));
4631       tmp->rotate(end,0,angle);
4632       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4633     }
4634   return ret.retn();
4635 }
4636
4637 /*!
4638  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4639  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4640  * \return newCoords new coords filled by this method. 
4641  */
4642 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4643 {
4644   if(isQuad)
4645     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4646   int oldNbOfNodes=getNumberOfNodes();
4647   int nbOf1DCells=mesh1D->getNumberOfCells();
4648   if(nbOf1DCells<2)
4649     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4650   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4651   int nbOfLevsInVec=nbOf1DCells+1;
4652   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4653   double *retPtr=ret->getPointer();
4654   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4655   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4656   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4657   tmp->setCoords(tmp2);
4658   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4659   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4660   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4661   for(int i=1;i<nbOfLevsInVec;i++)
4662     {
4663       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4664       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4665       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4666       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4667       tmp->translate(vec);
4668       double tmp3[2],radius,alpha,alpha0;
4669       const double *p0=i+1<nbOfLevsInVec?begin:third;
4670       const double *p1=i+1<nbOfLevsInVec?end:begin;
4671       const double *p2=i+1<nbOfLevsInVec?third:end;
4672       double vecPlane[3]={
4673         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4674         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4675         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4676       };
4677       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4678       if(norm>1.e-7)
4679         {
4680           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4681           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4682           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4683           double s2=norm2;
4684           double c2=cos(asin(s2));
4685           double m[3][3]={
4686             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4687             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4688             {-vec2[1]*s2, vec2[0]*s2, c2}
4689           };
4690           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]};
4691           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]};
4692           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]};
4693           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4694           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]);
4695           double angle=acos(cosangle/(radius*radius));
4696           tmp->rotate(end,vecPlane,angle);
4697           
4698         }
4699       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4700     }
4701   return ret.retn();
4702 }
4703
4704 /*!
4705  * This method is private because not easy to use for end user. This method is const contrary to
4706  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4707  * the coords sorted slice by slice.
4708  * \param isQuad specifies presence of quadratic cells.
4709  */
4710 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4711 {
4712   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4713   int nbOf2DCells=getNumberOfCells();
4714   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4715   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4716   const int *conn=_nodal_connec->getConstPointer();
4717   const int *connI=_nodal_connec_index->getConstPointer();
4718   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4719   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4720   newConnI->alloc(nbOf3DCells+1,1);
4721   int *newConnIPtr=newConnI->getPointer();
4722   *newConnIPtr++=0;
4723   std::vector<int> newc;
4724   for(int j=0;j<nbOf2DCells;j++)
4725     {
4726       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4727       *newConnIPtr++=(int)newc.size();
4728     }
4729   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4730   int *newConnPtr=newConn->getPointer();
4731   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4732   newConnIPtr=newConnI->getPointer();
4733   for(int iz=0;iz<nbOf1DCells;iz++)
4734     {
4735       if(iz!=0)
4736         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4737       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4738         {
4739           int icell=(int)(iter-newc.begin());
4740           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4741             {
4742               if(*iter!=-1)
4743                 *newConnPtr=(*iter)+iz*deltaPerLev;
4744               else
4745                 *newConnPtr=-1;
4746             }
4747           else
4748             *newConnPtr=(*iter);
4749         }
4750     }
4751   ret->setConnectivity(newConn,newConnI,true);
4752   ret->setCoords(getCoords());
4753   return ret;
4754 }
4755
4756 /*!
4757  * Checks if \a this mesh is constituted by only quadratic cells.
4758  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4759  *  \throw If the coordinates array is not set.
4760  *  \throw If the nodal connectivity of cells is not defined.
4761  */
4762 bool MEDCouplingUMesh::isFullyQuadratic() const
4763 {
4764   checkFullyDefined();
4765   bool ret=true;
4766   int nbOfCells=getNumberOfCells();
4767   for(int i=0;i<nbOfCells && ret;i++)
4768     {
4769       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4770       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4771       ret=cm.isQuadratic();
4772     }
4773   return ret;
4774 }
4775
4776 /*!
4777  * Checks if \a this mesh includes any quadratic cell.
4778  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4779  *  \throw If the coordinates array is not set.
4780  *  \throw If the nodal connectivity of cells is not defined.
4781  */
4782 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4783 {
4784   checkFullyDefined();
4785   bool ret=false;
4786   int nbOfCells=getNumberOfCells();
4787   for(int i=0;i<nbOfCells && !ret;i++)
4788     {
4789       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4790       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4791       ret=cm.isQuadratic();
4792     }
4793   return ret;
4794 }
4795
4796 /*!
4797  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4798  * this mesh, it remains unchanged.
4799  *  \throw If the coordinates array is not set.
4800  *  \throw If the nodal connectivity of cells is not defined.
4801  */
4802 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4803 {
4804   checkFullyDefined();
4805   int nbOfCells=getNumberOfCells();
4806   int delta=0;
4807   const int *iciptr=_nodal_connec_index->getConstPointer();
4808   for(int i=0;i<nbOfCells;i++)
4809     {
4810       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4811       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4812       if(cm.isQuadratic())
4813         {
4814           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4815           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4816           if(!cml.isDynamic())
4817             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4818           else
4819             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4820         }
4821     }
4822   if(delta==0)
4823     return ;
4824   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4825   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4826   const int *icptr=_nodal_connec->getConstPointer();
4827   newConn->alloc(getMeshLength()-delta,1);
4828   newConnI->alloc(nbOfCells+1,1);
4829   int *ocptr=newConn->getPointer();
4830   int *ociptr=newConnI->getPointer();
4831   *ociptr=0;
4832   _types.clear();
4833   for(int i=0;i<nbOfCells;i++,ociptr++)
4834     {
4835       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4836       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4837       if(!cm.isQuadratic())
4838         {
4839           _types.insert(type);
4840           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4841           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4842         }
4843       else
4844         {
4845           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4846           _types.insert(typel);
4847           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4848           int newNbOfNodes=cml.getNumberOfNodes();
4849           if(cml.isDynamic())
4850             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4851           *ocptr++=(int)typel;
4852           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4853           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4854         }
4855     }
4856   setConnectivity(newConn,newConnI,false);
4857 }
4858
4859 /*!
4860  * This method converts all linear cell in \a this to quadratic one.
4861  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4862  * 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)
4863  * 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.
4864  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4865  * end of the existing coordinates.
4866  * 
4867  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4868  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4869  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4870  * 
4871  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4872  *
4873  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4874  */
4875 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4876 {
4877   DataArrayInt *conn=0,*connI=0;
4878   DataArrayDouble *coords=0;
4879   std::set<INTERP_KERNEL::NormalizedCellType> types;
4880   checkFullyDefined();
4881   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4882   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4883   int meshDim=getMeshDimension();
4884   switch(conversionType)
4885     {
4886     case 0:
4887       switch(meshDim)
4888         {
4889         case 1:
4890           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4891           connSafe=conn; connISafe=connI; coordsSafe=coords;
4892           break;
4893         case 2:
4894           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4895           connSafe=conn; connISafe=connI; coordsSafe=coords;
4896           break;
4897         case 3:
4898           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4899           connSafe=conn; connISafe=connI; coordsSafe=coords;
4900           break;
4901         default:
4902           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4903         }
4904       break;
4905     case 1:
4906       {
4907         switch(meshDim)
4908         {
4909         case 1:
4910           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4911           connSafe=conn; connISafe=connI; coordsSafe=coords;
4912           break;
4913         case 2:
4914           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4915           connSafe=conn; connISafe=connI; coordsSafe=coords;
4916           break;
4917         case 3:
4918           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4919           connSafe=conn; connISafe=connI; coordsSafe=coords;
4920           break;
4921         default:
4922           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4923         }
4924         break;
4925       }
4926     default:
4927       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4928     }
4929   setConnectivity(connSafe,connISafe,false);
4930   _types=types;
4931   setCoords(coordsSafe);
4932   return ret.retn();
4933 }
4934
4935 /*!
4936  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4937  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4938  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4939  */
4940 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4941 {
4942   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4943   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4944   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4945   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4946   int nbOfCells=getNumberOfCells();
4947   int nbOfNodes=getNumberOfNodes();
4948   const int *cPtr=_nodal_connec->getConstPointer();
4949   const int *icPtr=_nodal_connec_index->getConstPointer();
4950   int lastVal=0,offset=nbOfNodes;
4951   for(int i=0;i<nbOfCells;i++,icPtr++)
4952     {
4953       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4954       if(type==INTERP_KERNEL::NORM_SEG2)
4955         {
4956           types.insert(INTERP_KERNEL::NORM_SEG3);
4957           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4958           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4959           newConn->pushBackSilent(offset++);
4960           lastVal+=4;
4961           newConnI->pushBackSilent(lastVal);
4962           ret->pushBackSilent(i);
4963         }
4964       else
4965         {
4966           types.insert(type);
4967           lastVal+=(icPtr[1]-icPtr[0]);
4968           newConnI->pushBackSilent(lastVal);
4969           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4970         }
4971     }
4972   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4973   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4974   return ret.retn();
4975 }
4976
4977 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
4978 {
4979   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4980   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4981   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4982   //
4983   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4984   DataArrayInt *conn1D=0,*conn1DI=0;
4985   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4986   DataArrayDouble *coordsTmp=0;
4987   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4988   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4989   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4990   const int *c1DPtr=conn1D->begin();
4991   const int *c1DIPtr=conn1DI->begin();
4992   int nbOfCells=getNumberOfCells();
4993   const int *cPtr=_nodal_connec->getConstPointer();
4994   const int *icPtr=_nodal_connec_index->getConstPointer();
4995   int lastVal=0;
4996   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4997     {
4998       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4999       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5000       if(!cm.isQuadratic())
5001         {
5002           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5003           types.insert(typ2); newConn->pushBackSilent(typ2);
5004           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5005           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5006             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5007           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5008           newConnI->pushBackSilent(lastVal);
5009           ret->pushBackSilent(i);
5010         }
5011       else
5012         {
5013           types.insert(typ);
5014           lastVal+=(icPtr[1]-icPtr[0]);
5015           newConnI->pushBackSilent(lastVal);
5016           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5017         }
5018     }
5019   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5020   return ret.retn();
5021 }
5022
5023 /*!
5024  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5025  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5026  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5027  */
5028 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5029 {
5030   
5031   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5032   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5033   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5034 }
5035
5036 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5037 {
5038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5039   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5040   //
5041   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5042   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5043   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5044   //
5045   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5046   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5047   DataArrayInt *conn1D=0,*conn1DI=0;
5048   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5049   DataArrayDouble *coordsTmp=0;
5050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5051   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5052   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5053   const int *c1DPtr=conn1D->begin();
5054   const int *c1DIPtr=conn1DI->begin();
5055   int nbOfCells=getNumberOfCells();
5056   const int *cPtr=_nodal_connec->getConstPointer();
5057   const int *icPtr=_nodal_connec_index->getConstPointer();
5058   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5059   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5060     {
5061       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5062       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5063       if(!cm.isQuadratic())
5064         {
5065           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5066           types.insert(typ2); newConn->pushBackSilent(typ2);
5067           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5068           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5069             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5070           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5071           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5072           newConnI->pushBackSilent(lastVal);
5073           ret->pushBackSilent(i);
5074         }
5075       else
5076         {
5077           types.insert(typ);
5078           lastVal+=(icPtr[1]-icPtr[0]);
5079           newConnI->pushBackSilent(lastVal);
5080           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5081         }
5082     }
5083   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5084   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5085   return ret.retn();
5086 }
5087
5088 /*!
5089  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5090  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5091  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5092  */
5093 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5094 {
5095   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5096   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5097   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5098 }
5099
5100 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5101 {
5102   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5103   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5105   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5106   //
5107   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5108   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5109   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5110   //
5111   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5112   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5113   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5114   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5115   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5116   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5117   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5118   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5119   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5120   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5122   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5123   int nbOfCells=getNumberOfCells();
5124   const int *cPtr=_nodal_connec->getConstPointer();
5125   const int *icPtr=_nodal_connec_index->getConstPointer();
5126   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5127   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5128     {
5129       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5130       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5131       if(!cm.isQuadratic())
5132         {
5133           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5134           if(typ2==INTERP_KERNEL::NORM_ERROR)
5135             {
5136               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5137               throw INTERP_KERNEL::Exception(oss.str().c_str());
5138             }
5139           types.insert(typ2); newConn->pushBackSilent(typ2);
5140           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5141           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5142             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5143           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5144             {
5145               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5146               int tmpPos=newConn->getNumberOfTuples();
5147               newConn->pushBackSilent(nodeId2);
5148               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5149             }
5150           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5151           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5152           newConnI->pushBackSilent(lastVal);
5153           ret->pushBackSilent(i);
5154         }
5155       else
5156         {
5157           types.insert(typ);
5158           lastVal+=(icPtr[1]-icPtr[0]);
5159           newConnI->pushBackSilent(lastVal);
5160           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5161         }
5162     }
5163   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5164   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5165   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5166   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5167   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5168   int *c=newConn->getPointer();
5169   const int *cI(newConnI->begin());
5170   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5171     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5172   offset=coordsTmp2Safe->getNumberOfTuples();
5173   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5174     c[cI[(*elt)+1]-1]+=offset;
5175   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5176   return ret.retn();
5177 }
5178
5179 /*!
5180  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5181  * so that the number of cells remains the same. Quadratic faces are converted to
5182  * polygons. This method works only for 2D meshes in
5183  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5184  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5185  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5186  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5187  *         a polylinized edge constituting the input polygon.
5188  *  \throw If the coordinates array is not set.
5189  *  \throw If the nodal connectivity of cells is not defined.
5190  *  \throw If \a this->getMeshDimension() != 2.
5191  *  \throw If \a this->getSpaceDimension() != 2.
5192  */
5193 void MEDCouplingUMesh::tessellate2D(double eps)
5194 {
5195   checkFullyDefined();
5196   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5197     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5198   double epsa=fabs(eps);
5199   if(epsa<std::numeric_limits<double>::min())
5200     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 !");
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5202   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5203   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5204   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5205   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5206   revDesc1=0; revDescIndx1=0;
5207   mDesc->tessellate2DCurve(eps);
5208   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5209   setCoords(mDesc->getCoords());
5210 }
5211
5212 /*!
5213  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5214  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5215  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5216  *         a sub-divided edge.
5217  *  \throw If the coordinates array is not set.
5218  *  \throw If the nodal connectivity of cells is not defined.
5219  *  \throw If \a this->getMeshDimension() != 1.
5220  *  \throw If \a this->getSpaceDimension() != 2.
5221  */
5222 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5223 {
5224   checkFullyDefined();
5225   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5226     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5227   double epsa=fabs(eps);
5228   if(epsa<std::numeric_limits<double>::min())
5229     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 !");
5230   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5231   int nbCells=getNumberOfCells();
5232   int nbNodes=getNumberOfNodes();
5233   const int *conn=_nodal_connec->getConstPointer();
5234   const int *connI=_nodal_connec_index->getConstPointer();
5235   const double *coords=_coords->getConstPointer();
5236   std::vector<double> addCoo;
5237   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5239   newConnI->alloc(nbCells+1,1);
5240   int *newConnIPtr=newConnI->getPointer();
5241   *newConnIPtr=0;
5242   int tmp1[3];
5243   INTERP_KERNEL::Node *tmp2[3];
5244   std::set<INTERP_KERNEL::NormalizedCellType> types;
5245   for(int i=0;i<nbCells;i++,newConnIPtr++)
5246     {
5247       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5248       if(cm.isQuadratic())
5249         {//assert(connI[i+1]-connI[i]-1==3)
5250           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5251           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5252           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5253           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5254           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5255           if(eac)
5256             {
5257               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5258               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5259               delete eac;
5260               newConnIPtr[1]=(int)newConn.size();
5261             }
5262           else
5263             {
5264               types.insert(INTERP_KERNEL::NORM_SEG2);
5265               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5266               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5267               newConnIPtr[1]=newConnIPtr[0]+3;
5268             }
5269         }
5270       else
5271         {
5272           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5273           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5274           newConnIPtr[1]=newConnIPtr[0]+3;
5275         }
5276     }
5277   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5278     return ;
5279   _types=types;
5280   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5281   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5282   newConnArr->alloc((int)newConn.size(),1);
5283   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5284   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5285   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5286   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5287   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5288   std::copy(addCoo.begin(),addCoo.end(),work);
5289   DataArrayDouble::SetArrayIn(newCoords,_coords);
5290   updateTime();
5291 }
5292
5293 /*!
5294  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5295  * In addition, returns an array mapping new cells to old ones. <br>
5296  * This method typically increases the number of cells in \a this mesh
5297  * but the number of nodes remains \b unchanged.
5298  * That's why the 3D splitting policies
5299  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5300  *  \param [in] policy - specifies a pattern used for splitting.
5301  * The semantic of \a policy is:
5302  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5303  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5304  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5305  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5306  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5307  *          an id of old cell producing it. The caller is to delete this array using
5308  *         decrRef() as it is no more needed. 
5309  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5310  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5311  *          and \a this->getMeshDimension() != 3. 
5312  *  \throw If \a policy is not one of the four discussed above.
5313  *  \throw If the nodal connectivity of cells is not defined.
5314  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5315  */
5316 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5317 {
5318   switch(policy)
5319     {
5320     case 0:
5321       return simplexizePol0();
5322     case 1:
5323       return simplexizePol1();
5324     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5325       return simplexizePlanarFace5();
5326     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5327       return simplexizePlanarFace6();
5328     default:
5329       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)");
5330     }
5331 }
5332
5333 /*!
5334  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5335  * - 1D: INTERP_KERNEL::NORM_SEG2
5336  * - 2D: INTERP_KERNEL::NORM_TRI3
5337  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5338  *
5339  * This method is useful for users that need to use P1 field services as
5340  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5341  * All these methods need mesh support containing only simplex cells.
5342  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5343  *  \throw If the coordinates array is not set.
5344  *  \throw If the nodal connectivity of cells is not defined.
5345  *  \throw If \a this->getMeshDimension() < 1.
5346  */
5347 bool MEDCouplingUMesh::areOnlySimplexCells() const
5348 {
5349   checkFullyDefined();
5350   int mdim=getMeshDimension();
5351   if(mdim<1 || mdim>3)
5352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5353   int nbCells=getNumberOfCells();
5354   const int *conn=_nodal_connec->getConstPointer();
5355   const int *connI=_nodal_connec_index->getConstPointer();
5356   for(int i=0;i<nbCells;i++)
5357     {
5358       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5359       if(!cm.isSimplex())
5360         return false;
5361     }
5362   return true;
5363 }
5364
5365 /*!
5366  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5367  */
5368 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5369 {
5370   checkConnectivityFullyDefined();
5371   if(getMeshDimension()!=2)
5372     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5373   int nbOfCells=getNumberOfCells();
5374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5375   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5376   ret->alloc(nbOfCells+nbOfCutCells,1);
5377   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5378   int *retPt=ret->getPointer();
5379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5380   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5381   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5382   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5383   int *pt=newConn->getPointer();
5384   int *ptI=newConnI->getPointer();
5385   ptI[0]=0;
5386   const int *oldc=_nodal_connec->getConstPointer();
5387   const int *ci=_nodal_connec_index->getConstPointer();
5388   for(int i=0;i<nbOfCells;i++,ci++)
5389     {
5390       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5391         {
5392           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5393                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5394           pt=std::copy(tmp,tmp+8,pt);
5395           ptI[1]=ptI[0]+4;
5396           ptI[2]=ptI[0]+8;
5397           *retPt++=i;
5398           *retPt++=i;
5399           ptI+=2;
5400         }
5401       else
5402         {
5403           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5404           ptI[1]=ptI[0]+ci[1]-ci[0];
5405           ptI++;
5406           *retPt++=i;
5407         }
5408     }
5409   _nodal_connec->decrRef();
5410   _nodal_connec=newConn.retn();
5411   _nodal_connec_index->decrRef();
5412   _nodal_connec_index=newConnI.retn();
5413   computeTypes();
5414   updateTime();
5415   return ret.retn();
5416 }
5417
5418 /*!
5419  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5420  */
5421 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5422 {
5423   checkConnectivityFullyDefined();
5424   if(getMeshDimension()!=2)
5425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5426   int nbOfCells=getNumberOfCells();
5427   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5428   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5429   ret->alloc(nbOfCells+nbOfCutCells,1);
5430   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5431   int *retPt=ret->getPointer();
5432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5433   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5434   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5435   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5436   int *pt=newConn->getPointer();
5437   int *ptI=newConnI->getPointer();
5438   ptI[0]=0;
5439   const int *oldc=_nodal_connec->getConstPointer();
5440   const int *ci=_nodal_connec_index->getConstPointer();
5441   for(int i=0;i<nbOfCells;i++,ci++)
5442     {
5443       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5444         {
5445           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5446                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5447           pt=std::copy(tmp,tmp+8,pt);
5448           ptI[1]=ptI[0]+4;
5449           ptI[2]=ptI[0]+8;
5450           *retPt++=i;
5451           *retPt++=i;
5452           ptI+=2;
5453         }
5454       else
5455         {
5456           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5457           ptI[1]=ptI[0]+ci[1]-ci[0];
5458           ptI++;
5459           *retPt++=i;
5460         }
5461     }
5462   _nodal_connec->decrRef();
5463   _nodal_connec=newConn.retn();
5464   _nodal_connec_index->decrRef();
5465   _nodal_connec_index=newConnI.retn();
5466   computeTypes();
5467   updateTime();
5468   return ret.retn();
5469 }
5470
5471 /*!
5472  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5473  */
5474 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5475 {
5476   checkConnectivityFullyDefined();
5477   if(getMeshDimension()!=3)
5478     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5479   int nbOfCells=getNumberOfCells();
5480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5481   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5482   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5483   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5484   int *retPt=ret->getPointer();
5485   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5486   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5487   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5488   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5489   int *pt=newConn->getPointer();
5490   int *ptI=newConnI->getPointer();
5491   ptI[0]=0;
5492   const int *oldc=_nodal_connec->getConstPointer();
5493   const int *ci=_nodal_connec_index->getConstPointer();
5494   for(int i=0;i<nbOfCells;i++,ci++)
5495     {
5496       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5497         {
5498           for(int j=0;j<5;j++,pt+=5,ptI++)
5499             {
5500               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5501               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];
5502               *retPt++=i;
5503               ptI[1]=ptI[0]+5;
5504             }
5505         }
5506       else
5507         {
5508           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5509           ptI[1]=ptI[0]+ci[1]-ci[0];
5510           ptI++;
5511           *retPt++=i;
5512         }
5513     }
5514   _nodal_connec->decrRef();
5515   _nodal_connec=newConn.retn();
5516   _nodal_connec_index->decrRef();
5517   _nodal_connec_index=newConnI.retn();
5518   computeTypes();
5519   updateTime();
5520   return ret.retn();
5521 }
5522
5523 /*!
5524  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5525  */
5526 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5527 {
5528   checkConnectivityFullyDefined();
5529   if(getMeshDimension()!=3)
5530     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5531   int nbOfCells=getNumberOfCells();
5532   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5533   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5534   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5535   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5536   int *retPt=ret->getPointer();
5537   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5538   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5539   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5540   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5541   int *pt=newConn->getPointer();
5542   int *ptI=newConnI->getPointer();
5543   ptI[0]=0;
5544   const int *oldc=_nodal_connec->getConstPointer();
5545   const int *ci=_nodal_connec_index->getConstPointer();
5546   for(int i=0;i<nbOfCells;i++,ci++)
5547     {
5548       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5549         {
5550           for(int j=0;j<6;j++,pt+=5,ptI++)
5551             {
5552               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5553               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];
5554               *retPt++=i;
5555               ptI[1]=ptI[0]+5;
5556             }
5557         }
5558       else
5559         {
5560           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5561           ptI[1]=ptI[0]+ci[1]-ci[0];
5562           ptI++;
5563           *retPt++=i;
5564         }
5565     }
5566   _nodal_connec->decrRef();
5567   _nodal_connec=newConn.retn();
5568   _nodal_connec_index->decrRef();
5569   _nodal_connec_index=newConnI.retn();
5570   computeTypes();
5571   updateTime();
5572   return ret.retn();
5573 }
5574
5575 /*!
5576  * 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.
5577  * This method completly ignore coordinates.
5578  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5579  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5580  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5581  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5582  */
5583 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5584 {
5585   checkFullyDefined();
5586   if(getMeshDimension()!=2)
5587     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5588   int nbOfCells=getNumberOfCells();
5589   int *connI=_nodal_connec_index->getPointer();
5590   int newConnLgth=0;
5591   for(int i=0;i<nbOfCells;i++,connI++)
5592     {
5593       int offset=descIndex[i];
5594       int nbOfEdges=descIndex[i+1]-offset;
5595       //
5596       bool ddirect=desc[offset+nbOfEdges-1]>0;
5597       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5598       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5599       for(int j=0;j<nbOfEdges;j++)
5600         {
5601           bool direct=desc[offset+j]>0;
5602           int edgeId=std::abs(desc[offset+j])-1;
5603           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5604             {
5605               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5606               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5607               int ref2=direct?id1:id2;
5608               if(ref==ref2)
5609                 {
5610                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5611                   newConnLgth+=nbOfSubNodes-1;
5612                   ref=direct?id2:id1;
5613                 }
5614               else
5615                 {
5616                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5617                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5618                 }
5619             }
5620           else
5621             {
5622               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5623             }
5624         }
5625       newConnLgth++;//+1 is for cell type
5626       connI[1]=newConnLgth;
5627     }
5628   //
5629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5630   newConn->alloc(newConnLgth,1);
5631   int *work=newConn->getPointer();
5632   for(int i=0;i<nbOfCells;i++)
5633     {
5634       *work++=INTERP_KERNEL::NORM_POLYGON;
5635       int offset=descIndex[i];
5636       int nbOfEdges=descIndex[i+1]-offset;
5637       for(int j=0;j<nbOfEdges;j++)
5638         {
5639           bool direct=desc[offset+j]>0;
5640           int edgeId=std::abs(desc[offset+j])-1;
5641           if(direct)
5642             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5643           else
5644             {
5645               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5646               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5647               work=std::copy(it,it+nbOfSubNodes-1,work);
5648             }
5649         }
5650     }
5651   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5652   _types.clear();
5653   if(nbOfCells>0)
5654     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5655 }
5656
5657 /*!
5658  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5659  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5660  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5661  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5662  * so it can be useful to call mergeNodes() before calling this method.
5663  *  \throw If \a this->getMeshDimension() <= 1.
5664  *  \throw If the coordinates array is not set.
5665  *  \throw If the nodal connectivity of cells is not defined.
5666  */
5667 void MEDCouplingUMesh::convertDegeneratedCells()
5668 {
5669   checkFullyDefined();
5670   if(getMeshDimension()<=1)
5671     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5672   int nbOfCells=getNumberOfCells();
5673   if(nbOfCells<1)
5674     return ;
5675   int initMeshLgth=getMeshLength();
5676   int *conn=_nodal_connec->getPointer();
5677   int *index=_nodal_connec_index->getPointer();
5678   int posOfCurCell=0;
5679   int newPos=0;
5680   int lgthOfCurCell;
5681   for(int i=0;i<nbOfCells;i++)
5682     {
5683       lgthOfCurCell=index[i+1]-posOfCurCell;
5684       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5685       int newLgth;
5686       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5687                                                                                                      conn+newPos+1,newLgth);
5688       conn[newPos]=newType;
5689       newPos+=newLgth+1;
5690       posOfCurCell=index[i+1];
5691       index[i+1]=newPos;
5692     }
5693   if(newPos!=initMeshLgth)
5694     _nodal_connec->reAlloc(newPos);
5695   computeTypes();
5696 }
5697
5698 /*!
5699  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5700  * A cell is considered to be oriented correctly if an angle between its
5701  * normal vector and a given vector is less than \c PI / \c 2.
5702  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5703  *         cells. 
5704  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5705  *         checked.
5706  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5707  *         is not cleared before filling in.
5708  *  \throw If \a this->getMeshDimension() != 2.
5709  *  \throw If \a this->getSpaceDimension() != 3.
5710  *
5711  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5712  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5713  */
5714 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5715 {
5716   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5717     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5718   int nbOfCells=getNumberOfCells();
5719   const int *conn=_nodal_connec->getConstPointer();
5720   const int *connI=_nodal_connec_index->getConstPointer();
5721   const double *coordsPtr=_coords->getConstPointer();
5722   for(int i=0;i<nbOfCells;i++)
5723     {
5724       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5725       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5726         {
5727           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5728           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5729             cells.push_back(i);
5730         }
5731     }
5732 }
5733
5734 /*!
5735  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5736  * considered to be oriented correctly if an angle between its normal vector and a
5737  * given vector is less than \c PI / \c 2. 
5738  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5739  *         cells. 
5740  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5741  *         checked.
5742  *  \throw If \a this->getMeshDimension() != 2.
5743  *  \throw If \a this->getSpaceDimension() != 3.
5744  *
5745  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5746  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5747  */
5748 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5749 {
5750   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5751     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5752   int nbOfCells=getNumberOfCells();
5753   int *conn=_nodal_connec->getPointer();
5754   const int *connI=_nodal_connec_index->getConstPointer();
5755   const double *coordsPtr=_coords->getConstPointer();
5756   bool isModified=false;
5757   for(int i=0;i<nbOfCells;i++)
5758     {
5759       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5760       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5761         {
5762           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5763           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5764             {
5765               isModified=true;
5766               if(!isQuadratic)
5767                 {
5768                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5769                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5770                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5771                 }
5772               else
5773                 {
5774                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5775                   std::vector<int> tmp0(sz-1),tmp1(sz);
5776                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5777                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5778                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5779                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5780                 }
5781             }
5782         }
5783     }
5784   if(isModified)
5785     _nodal_connec->declareAsNew();
5786   updateTime();
5787 }
5788
5789 /*!
5790  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5791  * oriented facets. The normal vector of the facet should point out of the cell.
5792  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5793  *         is not cleared before filling in.
5794  *  \throw If \a this->getMeshDimension() != 3.
5795  *  \throw If \a this->getSpaceDimension() != 3.
5796  *  \throw If the coordinates array is not set.
5797  *  \throw If the nodal connectivity of cells is not defined.
5798  *
5799  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5800  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5801  */
5802 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5803 {
5804   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5805     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5806   int nbOfCells=getNumberOfCells();
5807   const int *conn=_nodal_connec->getConstPointer();
5808   const int *connI=_nodal_connec_index->getConstPointer();
5809   const double *coordsPtr=_coords->getConstPointer();
5810   for(int i=0;i<nbOfCells;i++)
5811     {
5812       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5813       if(type==INTERP_KERNEL::NORM_POLYHED)
5814         {
5815           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5816             cells.push_back(i);
5817         }
5818     }
5819 }
5820
5821 /*!
5822  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5823  * out of the cell. 
5824  *  \throw If \a this->getMeshDimension() != 3.
5825  *  \throw If \a this->getSpaceDimension() != 3.
5826  *  \throw If the coordinates array is not set.
5827  *  \throw If the nodal connectivity of cells is not defined.
5828  *  \throw If the reparation fails.
5829  *
5830  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5831  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5832  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5833  */
5834 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5835 {
5836   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5837     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5838   int nbOfCells=getNumberOfCells();
5839   int *conn=_nodal_connec->getPointer();
5840   const int *connI=_nodal_connec_index->getConstPointer();
5841   const double *coordsPtr=_coords->getConstPointer();
5842   for(int i=0;i<nbOfCells;i++)
5843     {
5844       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5845       if(type==INTERP_KERNEL::NORM_POLYHED)
5846         {
5847           try
5848             {
5849               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5850                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5851             }
5852           catch(INTERP_KERNEL::Exception& e)
5853             {
5854               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5855               throw INTERP_KERNEL::Exception(oss.str().c_str());
5856             }
5857         }
5858     }
5859   updateTime();
5860 }
5861
5862 /*!
5863  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5864  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5865  * according to which the first facet of the cell should be oriented to have the normal vector
5866  * pointing out of cell.
5867  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5868  *         cells. The caller is to delete this array using decrRef() as it is no more
5869  *         needed. 
5870  *  \throw If \a this->getMeshDimension() != 3.
5871  *  \throw If \a this->getSpaceDimension() != 3.
5872  *  \throw If the coordinates array is not set.
5873  *  \throw If the nodal connectivity of cells is not defined.
5874  *
5875  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5876  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5877  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5878  */
5879 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5880 {
5881   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5882   if(getMeshDimension()!=3)
5883     throw INTERP_KERNEL::Exception(msg);
5884   int spaceDim=getSpaceDimension();
5885   if(spaceDim!=3)
5886     throw INTERP_KERNEL::Exception(msg);
5887   //
5888   int nbOfCells=getNumberOfCells();
5889   int *conn=_nodal_connec->getPointer();
5890   const int *connI=_nodal_connec_index->getConstPointer();
5891   const double *coo=getCoords()->getConstPointer();
5892   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5893   for(int i=0;i<nbOfCells;i++)
5894     {
5895       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5896       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5897         {
5898           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5899             {
5900               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5901               cells->pushBackSilent(i);
5902             }
5903         }
5904     }
5905   return cells.retn();
5906 }
5907
5908 /*!
5909  * This method is a faster method to correct orientation of all 3D cells in \a this.
5910  * 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.
5911  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5912  * 
5913  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5914  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5915  */
5916 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5917 {
5918   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5919     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5920   int nbOfCells=getNumberOfCells();
5921   int *conn=_nodal_connec->getPointer();
5922   const int *connI=_nodal_connec_index->getConstPointer();
5923   const double *coordsPtr=_coords->getConstPointer();
5924   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5925   for(int i=0;i<nbOfCells;i++)
5926     {
5927       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5928       switch(type)
5929         {
5930         case INTERP_KERNEL::NORM_TETRA4:
5931           {
5932             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5933               {
5934                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5935                 ret->pushBackSilent(i);
5936               }
5937             break;
5938           }
5939         case INTERP_KERNEL::NORM_PYRA5:
5940           {
5941             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5942               {
5943                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5944                 ret->pushBackSilent(i);
5945               }
5946             break;
5947           }
5948         case INTERP_KERNEL::NORM_PENTA6:
5949         case INTERP_KERNEL::NORM_HEXA8:
5950         case INTERP_KERNEL::NORM_HEXGP12:
5951           {
5952             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5953               {
5954                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5955                 ret->pushBackSilent(i);
5956               }
5957             break;
5958           }
5959         case INTERP_KERNEL::NORM_POLYHED:
5960           {
5961             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5962               {
5963                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5964                 ret->pushBackSilent(i);
5965               }
5966             break;
5967           }
5968         default:
5969           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 !");
5970         }
5971     }
5972   updateTime();
5973   return ret.retn();
5974 }
5975
5976 /*!
5977  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5978  * If it is not the case an exception will be thrown.
5979  * This method is fast because the first cell of \a this is used to compute the plane.
5980  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5981  * \param pos output of size at least 3 used to store a point owned of searched plane.
5982  */
5983 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5984 {
5985   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5986     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5987   const int *conn=_nodal_connec->getConstPointer();
5988   const int *connI=_nodal_connec_index->getConstPointer();
5989   const double *coordsPtr=_coords->getConstPointer();
5990   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5991   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5992 }
5993
5994 /*!
5995  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5996  * cells. Currently cells of the following types are treated:
5997  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5998  * For a cell of other type an exception is thrown.
5999  * Space dimension of a 2D mesh can be either 2 or 3.
6000  * The Edge Ratio of a cell \f$t\f$ is: 
6001  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6002  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6003  *  the smallest edge lengths of \f$t\f$.
6004  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6005  *          cells and one time, lying on \a this mesh. The caller is to delete this
6006  *          field using decrRef() as it is no more needed. 
6007  *  \throw If the coordinates array is not set.
6008  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6009  *  \throw If the connectivity data array has more than one component.
6010  *  \throw If the connectivity data array has a named component.
6011  *  \throw If the connectivity index data array has more than one component.
6012  *  \throw If the connectivity index data array has a named component.
6013  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6014  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6015  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6016  */
6017 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6018 {
6019   checkCoherency();
6020   int spaceDim=getSpaceDimension();
6021   int meshDim=getMeshDimension();
6022   if(spaceDim!=2 && spaceDim!=3)
6023     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6024   if(meshDim!=2 && meshDim!=3)
6025     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6026   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6027   ret->setMesh(this);
6028   int nbOfCells=getNumberOfCells();
6029   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6030   arr->alloc(nbOfCells,1);
6031   double *pt=arr->getPointer();
6032   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6033   const int *conn=_nodal_connec->getConstPointer();
6034   const int *connI=_nodal_connec_index->getConstPointer();
6035   const double *coo=_coords->getConstPointer();
6036   double tmp[12];
6037   for(int i=0;i<nbOfCells;i++,pt++)
6038     {
6039       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6040       switch(t)
6041         {
6042           case INTERP_KERNEL::NORM_TRI3:
6043             {
6044               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6045               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6046               break;
6047             }
6048           case INTERP_KERNEL::NORM_QUAD4:
6049             {
6050               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6051               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6052               break;
6053             }
6054           case INTERP_KERNEL::NORM_TETRA4:
6055             {
6056               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6057               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6058               break;
6059             }
6060         default:
6061           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6062         }
6063       conn+=connI[i+1]-connI[i];
6064     }
6065   ret->setName("EdgeRatio");
6066   ret->synchronizeTimeWithSupport();
6067   return ret.retn();
6068 }
6069
6070 /*!
6071  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6072  * cells. Currently cells of the following types are treated:
6073  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6074  * For a cell of other type an exception is thrown.
6075  * Space dimension of a 2D mesh can be either 2 or 3.
6076  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6077  *          cells and one time, lying on \a this mesh. The caller is to delete this
6078  *          field using decrRef() as it is no more needed. 
6079  *  \throw If the coordinates array is not set.
6080  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6081  *  \throw If the connectivity data array has more than one component.
6082  *  \throw If the connectivity data array has a named component.
6083  *  \throw If the connectivity index data array has more than one component.
6084  *  \throw If the connectivity index data array has a named component.
6085  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6086  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6087  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6088  */
6089 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6090 {
6091   checkCoherency();
6092   int spaceDim=getSpaceDimension();
6093   int meshDim=getMeshDimension();
6094   if(spaceDim!=2 && spaceDim!=3)
6095     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6096   if(meshDim!=2 && meshDim!=3)
6097     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6098   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6099   ret->setMesh(this);
6100   int nbOfCells=getNumberOfCells();
6101   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6102   arr->alloc(nbOfCells,1);
6103   double *pt=arr->getPointer();
6104   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6105   const int *conn=_nodal_connec->getConstPointer();
6106   const int *connI=_nodal_connec_index->getConstPointer();
6107   const double *coo=_coords->getConstPointer();
6108   double tmp[12];
6109   for(int i=0;i<nbOfCells;i++,pt++)
6110     {
6111       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6112       switch(t)
6113         {
6114           case INTERP_KERNEL::NORM_TRI3:
6115             {
6116               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6117               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6118               break;
6119             }
6120           case INTERP_KERNEL::NORM_QUAD4:
6121             {
6122               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6123               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6124               break;
6125             }
6126           case INTERP_KERNEL::NORM_TETRA4:
6127             {
6128               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6129               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6130               break;
6131             }
6132         default:
6133           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6134         }
6135       conn+=connI[i+1]-connI[i];
6136     }
6137   ret->setName("AspectRatio");
6138   ret->synchronizeTimeWithSupport();
6139   return ret.retn();
6140 }
6141
6142 /*!
6143  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6144  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6145  * treated: INTERP_KERNEL::NORM_QUAD4.
6146  * For a cell of other type an exception is thrown.
6147  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6148  *          cells and one time, lying on \a this mesh. The caller is to delete this
6149  *          field using decrRef() as it is no more needed. 
6150  *  \throw If the coordinates array is not set.
6151  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6152  *  \throw If the connectivity data array has more than one component.
6153  *  \throw If the connectivity data array has a named component.
6154  *  \throw If the connectivity index data array has more than one component.
6155  *  \throw If the connectivity index data array has a named component.
6156  *  \throw If \a this->getMeshDimension() != 2.
6157  *  \throw If \a this->getSpaceDimension() != 3.
6158  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6159  */
6160 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6161 {
6162   checkCoherency();
6163   int spaceDim=getSpaceDimension();
6164   int meshDim=getMeshDimension();
6165   if(spaceDim!=3)
6166     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6167   if(meshDim!=2)
6168     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6169   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6170   ret->setMesh(this);
6171   int nbOfCells=getNumberOfCells();
6172   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6173   arr->alloc(nbOfCells,1);
6174   double *pt=arr->getPointer();
6175   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6176   const int *conn=_nodal_connec->getConstPointer();
6177   const int *connI=_nodal_connec_index->getConstPointer();
6178   const double *coo=_coords->getConstPointer();
6179   double tmp[12];
6180   for(int i=0;i<nbOfCells;i++,pt++)
6181     {
6182       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6183       switch(t)
6184         {
6185           case INTERP_KERNEL::NORM_QUAD4:
6186             {
6187               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6188               *pt=INTERP_KERNEL::quadWarp(tmp);
6189               break;
6190             }
6191         default:
6192           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6193         }
6194       conn+=connI[i+1]-connI[i];
6195     }
6196   ret->setName("Warp");
6197   ret->synchronizeTimeWithSupport();
6198   return ret.retn();
6199 }
6200
6201
6202 /*!
6203  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6204  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6205  * treated: INTERP_KERNEL::NORM_QUAD4.
6206  * For a cell of other type an exception is thrown.
6207  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6208  *          cells and one time, lying on \a this mesh. The caller is to delete this
6209  *          field using decrRef() as it is no more needed. 
6210  *  \throw If the coordinates array is not set.
6211  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6212  *  \throw If the connectivity data array has more than one component.
6213  *  \throw If the connectivity data array has a named component.
6214  *  \throw If the connectivity index data array has more than one component.
6215  *  \throw If the connectivity index data array has a named component.
6216  *  \throw If \a this->getMeshDimension() != 2.
6217  *  \throw If \a this->getSpaceDimension() != 3.
6218  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6219  */
6220 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6221 {
6222   checkCoherency();
6223   int spaceDim=getSpaceDimension();
6224   int meshDim=getMeshDimension();
6225   if(spaceDim!=3)
6226     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6227   if(meshDim!=2)
6228     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6229   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6230   ret->setMesh(this);
6231   int nbOfCells=getNumberOfCells();
6232   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6233   arr->alloc(nbOfCells,1);
6234   double *pt=arr->getPointer();
6235   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6236   const int *conn=_nodal_connec->getConstPointer();
6237   const int *connI=_nodal_connec_index->getConstPointer();
6238   const double *coo=_coords->getConstPointer();
6239   double tmp[12];
6240   for(int i=0;i<nbOfCells;i++,pt++)
6241     {
6242       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6243       switch(t)
6244         {
6245           case INTERP_KERNEL::NORM_QUAD4:
6246             {
6247               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6248               *pt=INTERP_KERNEL::quadSkew(tmp);
6249               break;
6250             }
6251         default:
6252           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6253         }
6254       conn+=connI[i+1]-connI[i];
6255     }
6256   ret->setName("Skew");
6257   ret->synchronizeTimeWithSupport();
6258   return ret.retn();
6259 }
6260
6261 /*!
6262  * This method aggregate the bbox of each cell and put it into bbox parameter.
6263  * 
6264  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6265  *                         For all other cases this input parameter is ignored.
6266  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6267  * 
6268  * \throw If \a this is not fully set (coordinates and connectivity).
6269  * \throw If a cell in \a this has no valid nodeId.
6270  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6271  */
6272 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6273 {
6274   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6275   if((mDim==3 && sDim==3) || (mDim==2 && sDim==3) || (mDim==1 && sDim==1) || ( mDim==1 && sDim==3))  // Compute refined boundary box for quadratic elements only in 2D.
6276     return getBoundingBoxForBBTreeFast();
6277   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6278     {
6279       bool presenceOfQuadratic(false);
6280       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6281         {
6282           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6283           if(cm.isQuadratic())
6284             presenceOfQuadratic=true;
6285         }
6286       if(!presenceOfQuadratic)
6287         return getBoundingBoxForBBTreeFast();
6288       if(mDim==2 && sDim==2)
6289         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6290       else
6291         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6292     }
6293   throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree : Managed dimensions are (mDim=1,sDim=1), (mDim=1,sDim=2), (mDim=1,sDim=3), (mDim=2,sDim=2), (mDim=2,sDim=3) and (mDim=3,sDim=3) !");
6294 }
6295
6296 /*!
6297  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6298  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6299  * 
6300  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6301  * 
6302  * \throw If \a this is not fully set (coordinates and connectivity).
6303  * \throw If a cell in \a this has no valid nodeId.
6304  */
6305 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6306 {
6307   checkFullyDefined();
6308   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6309   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6310   double *bbox(ret->getPointer());
6311   for(int i=0;i<nbOfCells*spaceDim;i++)
6312     {
6313       bbox[2*i]=std::numeric_limits<double>::max();
6314       bbox[2*i+1]=-std::numeric_limits<double>::max();
6315     }
6316   const double *coordsPtr(_coords->getConstPointer());
6317   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6318   for(int i=0;i<nbOfCells;i++)
6319     {
6320       int offset=connI[i]+1;
6321       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6322       for(int j=0;j<nbOfNodesForCell;j++)
6323         {
6324           int nodeId=conn[offset+j];
6325           if(nodeId>=0 && nodeId<nbOfNodes)
6326             {
6327               for(int k=0;k<spaceDim;k++)
6328                 {
6329                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6330                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6331                 }
6332               kk++;
6333             }
6334         }
6335       if(kk==0)
6336         {
6337           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6338           throw INTERP_KERNEL::Exception(oss.str().c_str());
6339         }
6340     }
6341   return ret.retn();
6342 }
6343
6344 /*!
6345  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6346  * useful for 2D meshes having quadratic cells
6347  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6348  * the two extremities of the arc of circle).
6349  * 
6350  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6351  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6352  * \throw If \a this is not fully defined.
6353  * \throw If \a this is not a mesh with meshDimension equal to 2.
6354  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6355  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6356  */
6357 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6358 {
6359   checkFullyDefined();
6360   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6361   if(spaceDim!=2 || spaceDim!=2)
6362     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic : This method should be applied on mesh with mesh dimension equal to 2 and space dimension also equal to 2!");
6363   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6364   double *bbox(ret->getPointer());
6365   const double *coords(_coords->getConstPointer());
6366   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6367   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6368     {
6369       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6370       int sz(connI[1]-connI[0]-1);
6371       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6372       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6373       INTERP_KERNEL::QuadraticPolygon *pol(0);
6374       for(int j=0;j<sz;j++)
6375         {
6376           int nodeId(conn[*connI+1+j]);
6377           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6378         }
6379       if(!cm.isQuadratic())
6380         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6381       else
6382         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6383       INTERP_KERNEL::Bounds b; pol->fillBounds(b); delete pol;
6384       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6385     }
6386   return ret.retn();
6387 }
6388
6389 /*!
6390  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6391  * useful for 2D meshes having quadratic cells
6392  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6393  * the two extremities of the arc of circle).
6394  * 
6395  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6396  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6397  * \throw If \a this is not fully defined.
6398  * \throw If \a this is not a mesh with meshDimension equal to 1.
6399  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6400  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6401  */
6402 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6403 {
6404   checkFullyDefined();
6405   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6406   if(spaceDim!=2 || spaceDim!=2)
6407     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic : This method should be applied on mesh with mesh dimension equal to 1 and space dimension also equal to 2!");
6408   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6409   double *bbox(ret->getPointer());
6410   const double *coords(_coords->getConstPointer());
6411   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6412   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6413     {
6414       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6415       int sz(connI[1]-connI[0]-1);
6416       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6417       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6418       INTERP_KERNEL::Edge *edge(0);
6419       for(int j=0;j<sz;j++)
6420         {
6421           int nodeId(conn[*connI+1+j]);
6422           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6423         }
6424       if(!cm.isQuadratic())
6425         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6426       else
6427         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6428       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6429       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6430     }
6431   return ret.retn();
6432 }
6433
6434 /// @cond INTERNAL
6435
6436 namespace ParaMEDMEMImpl
6437 {
6438   class ConnReader
6439   {
6440   public:
6441     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6442     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6443   private:
6444     const int *_conn;
6445     int _val;
6446   };
6447
6448   class ConnReader2
6449   {
6450   public:
6451     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6452     bool operator() (const int& pos) { return _conn[pos]==_val; }
6453   private:
6454     const int *_conn;
6455     int _val;
6456   };
6457 }
6458
6459 /// @endcond
6460
6461 /*!
6462  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6463  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6464  * \a this is composed in cell types.
6465  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6466  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6467  * This parameter is kept only for compatibility with other methode listed above.
6468  */
6469 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6470 {
6471   checkConnectivityFullyDefined();
6472   const int *conn=_nodal_connec->getConstPointer();
6473   const int *connI=_nodal_connec_index->getConstPointer();
6474   const int *work=connI;
6475   int nbOfCells=getNumberOfCells();
6476   std::size_t n=getAllGeoTypes().size();
6477   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6478   std::set<INTERP_KERNEL::NormalizedCellType> types;
6479   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6480     {
6481       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6482       if(types.find(typ)!=types.end())
6483         {
6484           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6485           oss << " is not contiguous !";
6486           throw INTERP_KERNEL::Exception(oss.str().c_str());
6487         }
6488       types.insert(typ);
6489       ret[3*i]=typ;
6490       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6491       ret[3*i+1]=(int)std::distance(work,work2);
6492       work=work2;
6493     }
6494   return ret;
6495 }
6496
6497 /*!
6498  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6499  * only for types cell, type node is not managed.
6500  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6501  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6502  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6503  * If 2 or more same geometric type is in \a code and exception is thrown too.
6504  *
6505  * This method firstly checks
6506  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6507  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6508  * an exception is thrown too.
6509  * 
6510  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6511  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6512  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6513  */
6514 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6515 {
6516   if(code.empty())
6517     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6518   std::size_t sz=code.size();
6519   std::size_t n=sz/3;
6520   if(sz%3!=0)
6521     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6522   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6523   int nb=0;
6524   bool isNoPflUsed=true;
6525   for(std::size_t i=0;i<n;i++)
6526     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6527       {
6528         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6529         nb+=code[3*i+1];
6530         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6531           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6532         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6533       }
6534   if(types.size()!=n)
6535     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6536   if(isNoPflUsed)
6537     {
6538       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6539         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6540       if(types.size()==_types.size())
6541         return 0;
6542     }
6543   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6544   ret->alloc(nb,1);
6545   int *retPtr=ret->getPointer();
6546   const int *connI=_nodal_connec_index->getConstPointer();
6547   const int *conn=_nodal_connec->getConstPointer();
6548   int nbOfCells=getNumberOfCells();
6549   const int *i=connI;
6550   int kk=0;
6551   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6552     {
6553       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6554       int offset=(int)std::distance(connI,i);
6555       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6556       int nbOfCellsOfCurType=(int)std::distance(i,j);
6557       if(code[3*kk+2]==-1)
6558         for(int k=0;k<nbOfCellsOfCurType;k++)
6559           *retPtr++=k+offset;
6560       else
6561         {
6562           int idInIdsPerType=code[3*kk+2];
6563           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6564             {
6565               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6566               if(zePfl)
6567                 {
6568                   zePfl->checkAllocated();
6569                   if(zePfl->getNumberOfComponents()==1)
6570                     {
6571                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6572                         {
6573                           if(*k>=0 && *k<nbOfCellsOfCurType)
6574                             *retPtr=(*k)+offset;
6575                           else
6576                             {
6577                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6578                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6579                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6580                             }
6581                         }
6582                     }
6583                   else
6584                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6585                 }
6586               else
6587                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6588             }
6589           else
6590             {
6591               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6592               oss << " should be in [0," << idsPerType.size() << ") !";
6593               throw INTERP_KERNEL::Exception(oss.str().c_str());
6594             }
6595         }
6596       i=j;
6597     }
6598   return ret.retn();
6599 }
6600
6601 /*!
6602  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6603  * 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.
6604  * 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.
6605  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6606  * 
6607  * \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.
6608  * \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,
6609  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6610  * \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.
6611  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6612  * \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
6613  */
6614 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6615 {
6616   if(!profile)
6617     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6618   if(profile->getNumberOfComponents()!=1)
6619     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6620   checkConnectivityFullyDefined();
6621   const int *conn=_nodal_connec->getConstPointer();
6622   const int *connI=_nodal_connec_index->getConstPointer();
6623   int nbOfCells=getNumberOfCells();
6624   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6625   std::vector<int> typeRangeVals(1);
6626   for(const int *i=connI;i!=connI+nbOfCells;)
6627     {
6628       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6629       if(std::find(types.begin(),types.end(),curType)!=types.end())
6630         {
6631           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6632         }
6633       types.push_back(curType);
6634       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6635       typeRangeVals.push_back((int)std::distance(connI,i));
6636     }
6637   //
6638   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6639   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6640   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6641   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6642   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6643   //
6644   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6645   code.resize(3*nbOfCastsFinal);
6646   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6647   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6648   for(int i=0;i<nbOfCastsFinal;i++)
6649     {
6650       int castId=castsPresent->getIJ(i,0);
6651       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6652       idsInPflPerType2.push_back(tmp3);
6653       code[3*i]=(int)types[castId];
6654       code[3*i+1]=tmp3->getNumberOfTuples();
6655       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6656       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6657         {
6658           tmp4->copyStringInfoFrom(*profile);
6659           idsPerType2.push_back(tmp4);
6660           code[3*i+2]=(int)idsPerType2.size()-1;
6661         }
6662       else
6663         {
6664           code[3*i+2]=-1;
6665         }
6666     }
6667   std::size_t sz2=idsInPflPerType2.size();
6668   idsInPflPerType.resize(sz2);
6669   for(std::size_t i=0;i<sz2;i++)
6670     {
6671       DataArrayInt *locDa=idsInPflPerType2[i];
6672       locDa->incrRef();
6673       idsInPflPerType[i]=locDa;
6674     }
6675   std::size_t sz=idsPerType2.size();
6676   idsPerType.resize(sz);
6677   for(std::size_t i=0;i<sz;i++)
6678     {
6679       DataArrayInt *locDa=idsPerType2[i];
6680       locDa->incrRef();
6681       idsPerType[i]=locDa;
6682     }
6683 }
6684
6685 /*!
6686  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6687  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6688  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6689  * 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.
6690  */
6691 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6692 {
6693   checkFullyDefined();
6694   nM1LevMesh->checkFullyDefined();
6695   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6696     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6697   if(_coords!=nM1LevMesh->getCoords())
6698     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6699   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6700   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6701   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6702   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6703   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6704   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6705   tmp->setConnectivity(tmp0,tmp1);
6706   tmp->renumberCells(ret0->getConstPointer(),false);
6707   revDesc=tmp->getNodalConnectivity();
6708   revDescIndx=tmp->getNodalConnectivityIndex();
6709   DataArrayInt *ret=0;
6710   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6711     {
6712       int tmp2;
6713       ret->getMaxValue(tmp2);
6714       ret->decrRef();
6715       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6716       throw INTERP_KERNEL::Exception(oss.str().c_str());
6717     }
6718   nM1LevMeshIds=ret;
6719   //
6720   revDesc->incrRef();
6721   revDescIndx->incrRef();
6722   ret1->incrRef();
6723   ret0->incrRef();
6724   meshnM1Old2New=ret0;
6725   return ret1;
6726 }
6727
6728 /*!
6729  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6730  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6731  * in "Old to New" mode.
6732  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6733  *          this array using decrRef() as it is no more needed.
6734  *  \throw If the nodal connectivity of cells is not defined.
6735  */
6736 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6737 {
6738   checkConnectivityFullyDefined();
6739   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6740   renumberCells(ret->getConstPointer(),false);
6741   return ret.retn();
6742 }
6743
6744 /*!
6745  * This methods checks that cells are sorted by their types.
6746  * This method makes asumption (no check) that connectivity is correctly set before calling.
6747  */
6748 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6749 {
6750   checkFullyDefined();
6751   const int *conn=_nodal_connec->getConstPointer();
6752   const int *connI=_nodal_connec_index->getConstPointer();
6753   int nbOfCells=getNumberOfCells();
6754   std::set<INTERP_KERNEL::NormalizedCellType> types;
6755   for(const int *i=connI;i!=connI+nbOfCells;)
6756     {
6757       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6758       if(types.find(curType)!=types.end())
6759         return false;
6760       types.insert(curType);
6761       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6762     }
6763   return true;
6764 }
6765
6766 /*!
6767  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6768  * The geometric type order is specified by MED file.
6769  * 
6770  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6771  */
6772 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6773 {
6774   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6775 }
6776
6777 /*!
6778  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6779  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6780  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6781  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6782  */
6783 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6784 {
6785   checkFullyDefined();
6786   const int *conn=_nodal_connec->getConstPointer();
6787   const int *connI=_nodal_connec_index->getConstPointer();
6788   int nbOfCells=getNumberOfCells();
6789   if(nbOfCells==0)
6790     return true;
6791   int lastPos=-1;
6792   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6793   for(const int *i=connI;i!=connI+nbOfCells;)
6794     {
6795       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6796       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6797       if(isTypeExists!=orderEnd)
6798         {
6799           int pos=(int)std::distance(orderBg,isTypeExists);
6800           if(pos<=lastPos)
6801             return false;
6802           lastPos=pos;
6803           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6804         }
6805       else
6806         {
6807           if(sg.find(curType)==sg.end())
6808             {
6809               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6810               sg.insert(curType);
6811             }
6812           else
6813             return false;
6814         }
6815     }
6816   return true;
6817 }
6818
6819 /*!
6820  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6821  * 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
6822  * 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'.
6823  */
6824 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6825 {
6826   checkConnectivityFullyDefined();
6827   int nbOfCells=getNumberOfCells();
6828   const int *conn=_nodal_connec->getConstPointer();
6829   const int *connI=_nodal_connec_index->getConstPointer();
6830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6832   tmpa->alloc(nbOfCells,1);
6833   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6834   tmpb->fillWithZero();
6835   int *tmp=tmpa->getPointer();
6836   int *tmp2=tmpb->getPointer();
6837   for(const int *i=connI;i!=connI+nbOfCells;i++)
6838     {
6839       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6840       if(where!=orderEnd)
6841         {
6842           int pos=(int)std::distance(orderBg,where);
6843           tmp2[pos]++;
6844           tmp[std::distance(connI,i)]=pos;
6845         }
6846       else
6847         {
6848           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6849           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6850           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6851           throw INTERP_KERNEL::Exception(oss.str().c_str());
6852         }
6853     }
6854   nbPerType=tmpb.retn();
6855   return tmpa.retn();
6856 }
6857
6858 /*!
6859  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6860  *
6861  * \return a new object containing the old to new correspondance.
6862  *
6863  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6864  */
6865 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6866 {
6867   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6868 }
6869
6870 /*!
6871  * 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.
6872  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6873  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6874  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6875  */
6876 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6877 {
6878   DataArrayInt *nbPerType=0;
6879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6880   nbPerType->decrRef();
6881   return tmpa->buildPermArrPerLevel();
6882 }
6883
6884 /*!
6885  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6886  * The number of cells remains unchanged after the call of this method.
6887  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6888  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6889  *
6890  * \return the array giving the correspondance old to new.
6891  */
6892 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6893 {
6894   checkFullyDefined();
6895   computeTypes();
6896   const int *conn=_nodal_connec->getConstPointer();
6897   const int *connI=_nodal_connec_index->getConstPointer();
6898   int nbOfCells=getNumberOfCells();
6899   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6900   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6901     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6902       {
6903         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6904         types.push_back(curType);
6905         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6906       }
6907   DataArrayInt *ret=DataArrayInt::New();
6908   ret->alloc(nbOfCells,1);
6909   int *retPtr=ret->getPointer();
6910   std::fill(retPtr,retPtr+nbOfCells,-1);
6911   int newCellId=0;
6912   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6913     {
6914       for(const int *i=connI;i!=connI+nbOfCells;i++)
6915         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6916           retPtr[std::distance(connI,i)]=newCellId++;
6917     }
6918   renumberCells(retPtr,false);
6919   return ret;
6920 }
6921
6922 /*!
6923  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6924  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6925  * This method makes asumption that connectivity is correctly set before calling.
6926  */
6927 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6928 {
6929   checkConnectivityFullyDefined();
6930   const int *conn=_nodal_connec->getConstPointer();
6931   const int *connI=_nodal_connec_index->getConstPointer();
6932   int nbOfCells=getNumberOfCells();
6933   std::vector<MEDCouplingUMesh *> ret;
6934   for(const int *i=connI;i!=connI+nbOfCells;)
6935     {
6936       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6937       int beginCellId=(int)std::distance(connI,i);
6938       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6939       int endCellId=(int)std::distance(connI,i);
6940       int sz=endCellId-beginCellId;
6941       int *cells=new int[sz];
6942       for(int j=0;j<sz;j++)
6943         cells[j]=beginCellId+j;
6944       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6945       delete [] cells;
6946       ret.push_back(m);
6947     }
6948   return ret;
6949 }
6950
6951 /*!
6952  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6953  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6954  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6955  *
6956  * \return a newly allocated instance, that the caller must manage.
6957  * \throw If \a this contains more than one geometric type.
6958  * \throw If the nodal connectivity of \a this is not fully defined.
6959  * \throw If the internal data is not coherent.
6960  */
6961 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6962 {
6963   checkConnectivityFullyDefined();
6964     if(_types.size()!=1)
6965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6966   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6967   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6968   ret->setCoords(getCoords());
6969   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6970   if(retC)
6971     {
6972       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6973       retC->setNodalConnectivity(c);
6974     }
6975   else
6976     {
6977       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6978       if(!retD)
6979         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6980       DataArrayInt *c=0,*ci=0;
6981       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6982       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6983       retD->setNodalConnectivity(cs,cis);
6984     }
6985   return ret.retn();
6986 }
6987
6988 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6989 {
6990   checkConnectivityFullyDefined();
6991     if(_types.size()!=1)
6992     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6993   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6994   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6995   if(cm.isDynamic())
6996     {
6997       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6998       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6999       throw INTERP_KERNEL::Exception(oss.str().c_str());
7000     }
7001   int nbCells=getNumberOfCells();
7002   int typi=(int)typ;
7003   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7004   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7005   int *outPtr=connOut->getPointer();
7006   const int *conn=_nodal_connec->begin();
7007   const int *connI=_nodal_connec_index->begin();
7008   nbNodesPerCell++;
7009   for(int i=0;i<nbCells;i++,connI++)
7010     {
7011       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7012         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7013       else
7014         {
7015           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 << ") !";
7016           throw INTERP_KERNEL::Exception(oss.str().c_str());
7017         }
7018     }
7019   return connOut.retn();
7020 }
7021
7022 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7023 {
7024   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7025   checkConnectivityFullyDefined();
7026   if(_types.size()!=1)
7027     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7028   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7029   if(lgth<nbCells)
7030     throw INTERP_KERNEL::Exception(msg0);
7031   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7032   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7033   int *cp(c->getPointer()),*cip(ci->getPointer());
7034   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7035   cip[0]=0;
7036   for(int i=0;i<nbCells;i++,cip++,incip++)
7037     {
7038       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7039       int delta(stop-strt);
7040       if(delta>=1)
7041         {
7042           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7043             cp=std::copy(incp+strt,incp+stop,cp);
7044           else
7045             throw INTERP_KERNEL::Exception(msg0);
7046         }
7047       else
7048         throw INTERP_KERNEL::Exception(msg0);
7049       cip[1]=cip[0]+delta;
7050     }
7051   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7052 }
7053
7054 /*!
7055  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7056  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7057  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7058  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7059  * are not used here to avoid the build of big permutation array.
7060  *
7061  * \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
7062  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7063  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7064  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7065  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7066  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7067  * \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
7068  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7069  */
7070 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7071                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7072                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7073 {
7074   std::vector<const MEDCouplingUMesh *> ms2;
7075   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7076     if(*it)
7077       {
7078         (*it)->checkConnectivityFullyDefined();
7079         ms2.push_back(*it);
7080       }
7081   if(ms2.empty())
7082     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7083   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7084   int meshDim=ms2[0]->getMeshDimension();
7085   std::vector<const MEDCouplingUMesh *> m1ssm;
7086   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7087   //
7088   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7089   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7090   int fake=0,rk=0;
7091   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7092   ret1->alloc(0,1); ret2->alloc(0,1);
7093   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7094     {
7095       if(meshDim!=(*it)->getMeshDimension())
7096         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7097       if(refCoo!=(*it)->getCoords())
7098         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7099       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7100       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7101       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7102       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7103         {
7104           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7105           m1ssmSingleAuto.push_back(singleCell);
7106           m1ssmSingle.push_back(singleCell);
7107           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7108         }
7109     }
7110   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7111   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7112   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7113   for(std::size_t i=0;i<m1ssm.size();i++)
7114     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7115   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7116   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7117   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7118   return ret0.retn();
7119 }
7120
7121 /*!
7122  * This method returns a newly created DataArrayInt instance.
7123  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7124  */
7125 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7126 {
7127   checkFullyDefined();
7128   const int *conn=_nodal_connec->getConstPointer();
7129   const int *connIndex=_nodal_connec_index->getConstPointer();
7130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7131   for(const int *w=begin;w!=end;w++)
7132     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7133       ret->pushBackSilent(*w);
7134   return ret.retn();
7135 }
7136
7137 /*!
7138  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7139  * are in [0:getNumberOfCells())
7140  */
7141 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7142 {
7143   checkFullyDefined();
7144   const int *conn=_nodal_connec->getConstPointer();
7145   const int *connI=_nodal_connec_index->getConstPointer();
7146   int nbOfCells=getNumberOfCells();
7147   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7148   int *tmp=new int[nbOfCells];
7149   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7150     {
7151       int j=0;
7152       for(const int *i=connI;i!=connI+nbOfCells;i++)
7153         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7154           tmp[std::distance(connI,i)]=j++;
7155     }
7156   DataArrayInt *ret=DataArrayInt::New();
7157   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7158   ret->copyStringInfoFrom(*da);
7159   int *retPtr=ret->getPointer();
7160   const int *daPtr=da->getConstPointer();
7161   int nbOfElems=da->getNbOfElems();
7162   for(int k=0;k<nbOfElems;k++)
7163     retPtr[k]=tmp[daPtr[k]];
7164   delete [] tmp;
7165   return ret;
7166 }
7167
7168 /*!
7169  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7170  * This method \b works \b for mesh sorted by type.
7171  * cells whose ids is in 'idsPerGeoType' array.
7172  * This method conserves coords and name of mesh.
7173  */
7174 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7175 {
7176   std::vector<int> code=getDistributionOfTypes();
7177   std::size_t nOfTypesInThis=code.size()/3;
7178   int sz=0,szOfType=0;
7179   for(std::size_t i=0;i<nOfTypesInThis;i++)
7180     {
7181       if(code[3*i]!=type)
7182         sz+=code[3*i+1];
7183       else
7184         szOfType=code[3*i+1];
7185     }
7186   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7187     if(*work<0 || *work>=szOfType)
7188       {
7189         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7190         oss << ". It should be in [0," << szOfType << ") !";
7191         throw INTERP_KERNEL::Exception(oss.str().c_str());
7192       }
7193   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7194   int *idsPtr=idsTokeep->getPointer();
7195   int offset=0;
7196   for(std::size_t i=0;i<nOfTypesInThis;i++)
7197     {
7198       if(code[3*i]!=type)
7199         for(int j=0;j<code[3*i+1];j++)
7200           *idsPtr++=offset+j;
7201       else
7202         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7203       offset+=code[3*i+1];
7204     }
7205   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7206   ret->copyTinyInfoFrom(this);
7207   return ret.retn();
7208 }
7209
7210 /*!
7211  * This method returns a vector of size 'this->getNumberOfCells()'.
7212  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7213  */
7214 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7215 {
7216   int ncell=getNumberOfCells();
7217   std::vector<bool> ret(ncell);
7218   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7219   const int *c=getNodalConnectivity()->getConstPointer();
7220   for(int i=0;i<ncell;i++)
7221     {
7222       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7223       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7224       ret[i]=cm.isQuadratic();
7225     }
7226   return ret;
7227 }
7228
7229 /*!
7230  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7231  */
7232 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7233 {
7234   if(other->getType()!=UNSTRUCTURED)
7235     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7236   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7237   return MergeUMeshes(this,otherC);
7238 }
7239
7240 /*!
7241  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7242  * computed by averaging coordinates of cell nodes, so this method is not a right
7243  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7244  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7245  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7246  *          components. The caller is to delete this array using decrRef() as it is
7247  *          no more needed.
7248  *  \throw If the coordinates array is not set.
7249  *  \throw If the nodal connectivity of cells is not defined.
7250  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7251  */
7252 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7253 {
7254   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7255   int spaceDim=getSpaceDimension();
7256   int nbOfCells=getNumberOfCells();
7257   ret->alloc(nbOfCells,spaceDim);
7258   ret->copyStringInfoFrom(*getCoords());
7259   double *ptToFill=ret->getPointer();
7260   const int *nodal=_nodal_connec->getConstPointer();
7261   const int *nodalI=_nodal_connec_index->getConstPointer();
7262   const double *coor=_coords->getConstPointer();
7263   for(int i=0;i<nbOfCells;i++)
7264     {
7265       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7266       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7267       ptToFill+=spaceDim;
7268     }
7269   return ret.retn();
7270 }
7271
7272 /*!
7273  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7274  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7275  * 
7276  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7277  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7278  * 
7279  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7280  * \throw If \a this is not fully defined (coordinates and connectivity)
7281  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7282  */
7283 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7284 {
7285   checkFullyDefined();
7286   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7287   int spaceDim=getSpaceDimension();
7288   int nbOfCells=getNumberOfCells();
7289   int nbOfNodes=getNumberOfNodes();
7290   ret->alloc(nbOfCells,spaceDim);
7291   double *ptToFill=ret->getPointer();
7292   const int *nodal=_nodal_connec->getConstPointer();
7293   const int *nodalI=_nodal_connec_index->getConstPointer();
7294   const double *coor=_coords->getConstPointer();
7295   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7296     {
7297       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7298       std::fill(ptToFill,ptToFill+spaceDim,0.);
7299       if(type!=INTERP_KERNEL::NORM_POLYHED)
7300         {
7301           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7302             {
7303               if(*conn>=0 && *conn<nbOfNodes)
7304                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7305               else
7306                 {
7307                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7308                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7309                 }
7310             }
7311           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7312           if(nbOfNodesInCell>0)
7313             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7314           else
7315             {
7316               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7317               throw INTERP_KERNEL::Exception(oss.str().c_str());
7318             }
7319         }
7320       else
7321         {
7322           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7323           s.erase(-1);
7324           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7325             {
7326               if(*it>=0 && *it<nbOfNodes)
7327                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7328               else
7329                 {
7330                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7331                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7332                 }
7333             }
7334           if(!s.empty())
7335             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7336           else
7337             {
7338               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7339               throw INTERP_KERNEL::Exception(oss.str().c_str());
7340             }
7341         }
7342     }
7343   return ret.retn();
7344 }
7345
7346 /*!
7347  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7348  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7349  * are specified via an array of cell ids. 
7350  *  \warning Validity of the specified cell ids is not checked! 
7351  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7352  *  \param [in] begin - an array of cell ids of interest.
7353  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7354  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7355  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7356  *          caller is to delete this array using decrRef() as it is no more needed. 
7357  *  \throw If the coordinates array is not set.
7358  *  \throw If the nodal connectivity of cells is not defined.
7359  *
7360  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7361  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7362  */
7363 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7364 {
7365   DataArrayDouble *ret=DataArrayDouble::New();
7366   int spaceDim=getSpaceDimension();
7367   int nbOfTuple=(int)std::distance(begin,end);
7368   ret->alloc(nbOfTuple,spaceDim);
7369   double *ptToFill=ret->getPointer();
7370   double *tmp=new double[spaceDim];
7371   const int *nodal=_nodal_connec->getConstPointer();
7372   const int *nodalI=_nodal_connec_index->getConstPointer();
7373   const double *coor=_coords->getConstPointer();
7374   for(const int *w=begin;w!=end;w++)
7375     {
7376       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7377       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7378       ptToFill+=spaceDim;
7379     }
7380   delete [] tmp;
7381   return ret;
7382 }
7383
7384 /*!
7385  * Returns a DataArrayDouble instance giving for each cell in \a this the equation of plane given by "a*X+b*Y+c*Z+d=0".
7386  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7387  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7388  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7389  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7390  * 
7391  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7392  * \throw If spaceDim!=3 or meshDim!=2.
7393  * \throw If connectivity of \a this is invalid.
7394  * \throw If connectivity of a cell in \a this points to an invalid node.
7395  */
7396 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7397 {
7398   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7399   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7400   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7401     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7402   ret->alloc(nbOfCells,4);
7403   double *retPtr(ret->getPointer());
7404   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7405   const double *coor(_coords->begin());
7406   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7407     {
7408       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7409       if(nodalI[1]-nodalI[0]>=3)
7410         {
7411           for(int j=0;j<3;j++)
7412             {
7413               int nodeId(nodal[nodalI[0]+1+j]);
7414               if(nodeId>=0 && nodeId<nbOfNodes)
7415                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7416               else
7417                 {
7418                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7419                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7420                 }
7421             }
7422         }
7423       else
7424         {
7425           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7426           throw INTERP_KERNEL::Exception(oss.str().c_str());
7427         }
7428       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7429       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7430     }
7431   return ret.retn();
7432 }
7433
7434 /*!
7435  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7436  * 
7437  */
7438 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7439 {
7440   if(!da)
7441     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7442   da->checkAllocated();
7443   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7444   ret->setCoords(da);
7445   int nbOfTuples=da->getNumberOfTuples();
7446   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7447   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7448   c->alloc(2*nbOfTuples,1);
7449   cI->alloc(nbOfTuples+1,1);
7450   int *cp=c->getPointer();
7451   int *cip=cI->getPointer();
7452   *cip++=0;
7453   for(int i=0;i<nbOfTuples;i++)
7454     {
7455       *cp++=INTERP_KERNEL::NORM_POINT1;
7456       *cp++=i;
7457       *cip++=2*(i+1);
7458     }
7459   ret->setConnectivity(c,cI,true);
7460   return ret.retn();
7461 }
7462 /*!
7463  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7464  * Cells and nodes of
7465  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7466  *  \param [in] mesh1 - the first mesh.
7467  *  \param [in] mesh2 - the second mesh.
7468  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7469  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7470  *          is no more needed.
7471  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7472  *  \throw If the coordinates array is not set in none of the meshes.
7473  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7474  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7475  */
7476 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7477 {
7478   std::vector<const MEDCouplingUMesh *> tmp(2);
7479   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7480   return MergeUMeshes(tmp);
7481 }
7482
7483 /*!
7484  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7485  * Cells and nodes of
7486  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7487  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7488  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7489  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7490  *          is no more needed.
7491  *  \throw If \a a.size() == 0.
7492  *  \throw If \a a[ *i* ] == NULL.
7493  *  \throw If the coordinates array is not set in none of the meshes.
7494  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7495  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7496 */
7497 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7498 {
7499   std::size_t sz=a.size();
7500   if(sz==0)
7501     return MergeUMeshesLL(a);
7502   for(std::size_t ii=0;ii<sz;ii++)
7503     if(!a[ii])
7504       {
7505         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7506         throw INTERP_KERNEL::Exception(oss.str().c_str());
7507       }
7508   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7509   std::vector< const MEDCouplingUMesh * > aa(sz);
7510   int spaceDim=-3;
7511   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7512     {
7513       const MEDCouplingUMesh *cur=a[i];
7514       const DataArrayDouble *coo=cur->getCoords();
7515       if(coo)
7516         spaceDim=coo->getNumberOfComponents();
7517     }
7518   if(spaceDim==-3)
7519     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7520   for(std::size_t i=0;i<sz;i++)
7521     {
7522       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7523       aa[i]=bb[i];
7524     }
7525   return MergeUMeshesLL(aa);
7526 }
7527
7528 /// @cond INTERNAL
7529
7530 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7531 {
7532   if(a.empty())
7533     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7534   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7535   int meshDim=(*it)->getMeshDimension();
7536   int nbOfCells=(*it)->getNumberOfCells();
7537   int meshLgth=(*it++)->getMeshLength();
7538   for(;it!=a.end();it++)
7539     {
7540       if(meshDim!=(*it)->getMeshDimension())
7541         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7542       nbOfCells+=(*it)->getNumberOfCells();
7543       meshLgth+=(*it)->getMeshLength();
7544     }
7545   std::vector<const MEDCouplingPointSet *> aps(a.size());
7546   std::copy(a.begin(),a.end(),aps.begin());
7547   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7548   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7549   ret->setCoords(pts);
7550   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7551   c->alloc(meshLgth,1);
7552   int *cPtr=c->getPointer();
7553   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7554   cI->alloc(nbOfCells+1,1);
7555   int *cIPtr=cI->getPointer();
7556   *cIPtr++=0;
7557   int offset=0;
7558   int offset2=0;
7559   for(it=a.begin();it!=a.end();it++)
7560     {
7561       int curNbOfCell=(*it)->getNumberOfCells();
7562       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7563       const int *curC=(*it)->_nodal_connec->getConstPointer();
7564       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7565       for(int j=0;j<curNbOfCell;j++)
7566         {
7567           const int *src=curC+curCI[j];
7568           *cPtr++=*src++;
7569           for(;src!=curC+curCI[j+1];src++,cPtr++)
7570             {
7571               if(*src!=-1)
7572                 *cPtr=*src+offset2;
7573               else
7574                 *cPtr=-1;
7575             }
7576         }
7577       offset+=curCI[curNbOfCell];
7578       offset2+=(*it)->getNumberOfNodes();
7579     }
7580   //
7581   ret->setConnectivity(c,cI,true);
7582   return ret.retn();
7583 }
7584
7585 /// @endcond
7586
7587 /*!
7588  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7589  * dimension and sharing the node coordinates array.
7590  * All cells of the first mesh precede all cells of the second mesh
7591  * within the result mesh. 
7592  *  \param [in] mesh1 - the first mesh.
7593  *  \param [in] mesh2 - the second mesh.
7594  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7595  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7596  *          is no more needed.
7597  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7598  *  \throw If the meshes do not share the node coordinates array.
7599  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7600  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7601  */
7602 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7603 {
7604   std::vector<const MEDCouplingUMesh *> tmp(2);
7605   tmp[0]=mesh1; tmp[1]=mesh2;
7606   return MergeUMeshesOnSameCoords(tmp);
7607 }
7608
7609 /*!
7610  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7611  * dimension and sharing the node coordinates array.
7612  * All cells of the *i*-th mesh precede all cells of the
7613  * (*i*+1)-th mesh within the result mesh.
7614  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7615  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7616  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7617  *          is no more needed.
7618  *  \throw If \a a.size() == 0.
7619  *  \throw If \a a[ *i* ] == NULL.
7620  *  \throw If the meshes do not share the node coordinates array.
7621  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7622  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7623  */
7624 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7625 {
7626   if(meshes.empty())
7627     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7628   for(std::size_t ii=0;ii<meshes.size();ii++)
7629     if(!meshes[ii])
7630       {
7631         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7632         throw INTERP_KERNEL::Exception(oss.str().c_str());
7633       }
7634   const DataArrayDouble *coords=meshes.front()->getCoords();
7635   int meshDim=meshes.front()->getMeshDimension();
7636   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7637   int meshLgth=0;
7638   int meshIndexLgth=0;
7639   for(;iter!=meshes.end();iter++)
7640     {
7641       if(coords!=(*iter)->getCoords())
7642         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7643       if(meshDim!=(*iter)->getMeshDimension())
7644         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7645       meshLgth+=(*iter)->getMeshLength();
7646       meshIndexLgth+=(*iter)->getNumberOfCells();
7647     }
7648   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7649   nodal->alloc(meshLgth,1);
7650   int *nodalPtr=nodal->getPointer();
7651   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7652   nodalIndex->alloc(meshIndexLgth+1,1);
7653   int *nodalIndexPtr=nodalIndex->getPointer();
7654   int offset=0;
7655   for(iter=meshes.begin();iter!=meshes.end();iter++)
7656     {
7657       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7658       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7659       int nbOfCells=(*iter)->getNumberOfCells();
7660       int meshLgth2=(*iter)->getMeshLength();
7661       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7662       if(iter!=meshes.begin())
7663         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7664       else
7665         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7666       offset+=meshLgth2;
7667     }
7668   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7669   ret->setName("merge");
7670   ret->setMeshDimension(meshDim);
7671   ret->setConnectivity(nodal,nodalIndex,true);
7672   ret->setCoords(coords);
7673   return ret;
7674 }
7675
7676 /*!
7677  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7678  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7679  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7680  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7681  * New" mode are returned for each input mesh.
7682  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7683  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7684  *          valid values [0,1,2], see zipConnectivityTraducer().
7685  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7686  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7687  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7688  *          no more needed.
7689  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7690  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7691  *          is no more needed.
7692  *  \throw If \a meshes.size() == 0.
7693  *  \throw If \a meshes[ *i* ] == NULL.
7694  *  \throw If the meshes do not share the node coordinates array.
7695  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7696  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7697  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7698  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7699  */
7700 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7701 {
7702   //All checks are delegated to MergeUMeshesOnSameCoords
7703   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7704   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7705   corr.resize(meshes.size());
7706   std::size_t nbOfMeshes=meshes.size();
7707   int offset=0;
7708   const int *o2nPtr=o2n->getConstPointer();
7709   for(std::size_t i=0;i<nbOfMeshes;i++)
7710     {
7711       DataArrayInt *tmp=DataArrayInt::New();
7712       int curNbOfCells=meshes[i]->getNumberOfCells();
7713       tmp->alloc(curNbOfCells,1);
7714       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7715       offset+=curNbOfCells;
7716       tmp->setName(meshes[i]->getName());
7717       corr[i]=tmp;
7718     }
7719   return ret.retn();
7720 }
7721
7722 /*!
7723  * Makes all given meshes share the nodal connectivity array. The common connectivity
7724  * array is created by concatenating the connectivity arrays of all given meshes. All
7725  * the given meshes must be of the same space dimension but dimension of cells **can
7726  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7727  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7728  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7729  *  \param [in,out] meshes - a vector of meshes to update.
7730  *  \throw If any of \a meshes is NULL.
7731  *  \throw If the coordinates array is not set in any of \a meshes.
7732  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7733  *  \throw If \a meshes are of different space dimension.
7734  */
7735 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7736 {
7737   std::size_t sz=meshes.size();
7738   if(sz==0 || sz==1)
7739     return;
7740   std::vector< const DataArrayDouble * > coords(meshes.size());
7741   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7742   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7743     {
7744       if((*it))
7745         {
7746           (*it)->checkConnectivityFullyDefined();
7747           const DataArrayDouble *coo=(*it)->getCoords();
7748           if(coo)
7749             *it2=coo;
7750           else
7751             {
7752               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7753               oss << " has no coordinate array defined !";
7754               throw INTERP_KERNEL::Exception(oss.str().c_str());
7755             }
7756         }
7757       else
7758         {
7759           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7760           oss << " is null !";
7761           throw INTERP_KERNEL::Exception(oss.str().c_str());
7762         }
7763     }
7764   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7765   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7766   int offset=(*it)->getNumberOfNodes();
7767   (*it++)->setCoords(res);
7768   for(;it!=meshes.end();it++)
7769     {
7770       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7771       (*it)->setCoords(res);
7772       (*it)->shiftNodeNumbersInConn(offset);
7773       offset+=oldNumberOfNodes;
7774     }
7775 }
7776
7777 /*!
7778  * Merges nodes coincident with a given precision within all given meshes that share
7779  * the nodal connectivity array. The given meshes **can be of different** mesh
7780  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7781  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7782  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7783  *  \param [in,out] meshes - a vector of meshes to update.
7784  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7785  *  \throw If any of \a meshes is NULL.
7786  *  \throw If the \a meshes do not share the same node coordinates array.
7787  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7788  */
7789 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7790 {
7791   if(meshes.empty())
7792     return ;
7793   std::set<const DataArrayDouble *> s;
7794   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7795     {
7796       if(*it)
7797         s.insert((*it)->getCoords());
7798       else
7799         {
7800           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 !";
7801           throw INTERP_KERNEL::Exception(oss.str().c_str());
7802         }
7803     }
7804   if(s.size()!=1)
7805     {
7806       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 !";
7807       throw INTERP_KERNEL::Exception(oss.str().c_str());
7808     }
7809   const DataArrayDouble *coo=*(s.begin());
7810   if(!coo)
7811     return;
7812   //
7813   DataArrayInt *comm,*commI;
7814   coo->findCommonTuples(eps,-1,comm,commI);
7815   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7816   int oldNbOfNodes=coo->getNumberOfTuples();
7817   int newNbOfNodes;
7818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7819   if(oldNbOfNodes==newNbOfNodes)
7820     return ;
7821   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7822   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7823     {
7824       (*it)->renumberNodesInConn(o2n->getConstPointer());
7825       (*it)->setCoords(newCoords);
7826     } 
7827 }
7828
7829 /*!
7830  * 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.
7831  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7832  * \param isQuad specifies the policy of connectivity.
7833  * @ret in/out parameter in which the result will be append
7834  */
7835 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7836 {
7837   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7838   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7839   ret.push_back(cm.getExtrudedType());
7840   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7841   switch(flatType)
7842     {
7843     case INTERP_KERNEL::NORM_POINT1:
7844       {
7845         ret.push_back(connBg[1]);
7846         ret.push_back(connBg[1]+nbOfNodesPerLev);
7847         break;
7848       }
7849     case INTERP_KERNEL::NORM_SEG2:
7850       {
7851         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7852         ret.insert(ret.end(),conn,conn+4);
7853         break;
7854       }
7855     case INTERP_KERNEL::NORM_SEG3:
7856       {
7857         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7858         ret.insert(ret.end(),conn,conn+8);
7859         break;
7860       }
7861     case INTERP_KERNEL::NORM_QUAD4:
7862       {
7863         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7864         ret.insert(ret.end(),conn,conn+8);
7865         break;
7866       }
7867     case INTERP_KERNEL::NORM_TRI3:
7868       {
7869         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7870         ret.insert(ret.end(),conn,conn+6);
7871         break;
7872       }
7873     case INTERP_KERNEL::NORM_TRI6:
7874       {
7875         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,
7876                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7877         ret.insert(ret.end(),conn,conn+15);
7878         break;
7879       }
7880     case INTERP_KERNEL::NORM_QUAD8:
7881       {
7882         int conn[20]={
7883           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7884           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7885           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7886         };
7887         ret.insert(ret.end(),conn,conn+20);
7888         break;
7889       }
7890     case INTERP_KERNEL::NORM_POLYGON:
7891       {
7892         std::back_insert_iterator< std::vector<int> > ii(ret);
7893         std::copy(connBg+1,connEnd,ii);
7894         *ii++=-1;
7895         std::reverse_iterator<const int *> rConnBg(connEnd);
7896         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7897         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7898         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7899         for(std::size_t i=0;i<nbOfRadFaces;i++)
7900           {
7901             *ii++=-1;
7902             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7903             std::copy(conn,conn+4,ii);
7904           }
7905         break;
7906       }
7907     default:
7908       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7909     }
7910 }
7911
7912 /*!
7913  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7914  */
7915 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7916 {
7917   double v[3]={0.,0.,0.};
7918   std::size_t sz=std::distance(begin,end);
7919   if(isQuadratic)
7920     sz/=2;
7921   for(std::size_t i=0;i<sz;i++)
7922     {
7923       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];
7924       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7925       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7926     }
7927   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7928 }
7929
7930 /*!
7931  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7932  */
7933 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7934 {
7935   std::vector<std::pair<int,int> > edges;
7936   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7937   const int *bgFace=begin;
7938   for(std::size_t i=0;i<nbOfFaces;i++)
7939     {
7940       const int *endFace=std::find(bgFace+1,end,-1);
7941       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7942       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7943         {
7944           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7945           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7946             return false;
7947           edges.push_back(p1);
7948         }
7949       bgFace=endFace+1;
7950     }
7951   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7952 }
7953
7954 /*!
7955  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7956  */
7957 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7958 {
7959   double vec0[3],vec1[3];
7960   std::size_t sz=std::distance(begin,end);
7961   if(sz%2!=0)
7962     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7963   int nbOfNodes=(int)sz/2;
7964   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7965   const double *pt0=coords+3*begin[0];
7966   const double *pt1=coords+3*begin[nbOfNodes];
7967   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7968   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7969 }
7970
7971 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7972 {
7973   std::size_t sz=std::distance(begin,end);
7974   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7975   std::size_t nbOfNodes(sz/2);
7976   std::copy(begin,end,(int *)tmp);
7977   for(std::size_t j=1;j<nbOfNodes;j++)
7978     {
7979       begin[j]=tmp[nbOfNodes-j];
7980       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7981     }
7982 }
7983
7984 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7985 {
7986   std::size_t sz=std::distance(begin,end);
7987   if(sz!=4)
7988     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7989   double vec0[3],vec1[3];
7990   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7991   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]; 
7992   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;
7993 }
7994
7995 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7996 {
7997   std::size_t sz=std::distance(begin,end);
7998   if(sz!=5)
7999     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8000   double vec0[3];
8001   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8002   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8003   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8004 }
8005
8006 /*!
8007  * 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 ) 
8008  * 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
8009  * a 2D space.
8010  *
8011  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8012  * \param [in] coords the coordinates with nb of components exactly equal to 3
8013  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8014  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8015  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8016  */
8017 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8018 {
8019   int nbFaces=std::count(begin+1,end,-1)+1;
8020   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8021   double *vPtr=v->getPointer();
8022   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8023   double *pPtr=p->getPointer();
8024   const int *stFaceConn=begin+1;
8025   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8026     {
8027       const int *endFaceConn=std::find(stFaceConn,end,-1);
8028       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8029       stFaceConn=endFaceConn+1;
8030     }
8031   pPtr=p->getPointer(); vPtr=v->getPointer();
8032   DataArrayInt *comm1=0,*commI1=0;
8033   v->findCommonTuples(eps,-1,comm1,commI1);
8034   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8035   const int *comm1Ptr=comm1->getConstPointer();
8036   const int *commI1Ptr=commI1->getConstPointer();
8037   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8038   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8039   //
8040   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8041   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8042   mm->finishInsertingCells();
8043   //
8044   for(int i=0;i<nbOfGrps1;i++)
8045     {
8046       int vecId=comm1Ptr[commI1Ptr[i]];
8047       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8048       DataArrayInt *comm2=0,*commI2=0;
8049       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8050       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8051       const int *comm2Ptr=comm2->getConstPointer();
8052       const int *commI2Ptr=commI2->getConstPointer();
8053       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8054       for(int j=0;j<nbOfGrps2;j++)
8055         {
8056           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8057             {
8058               res->insertAtTheEnd(begin,end);
8059               res->pushBackSilent(-1);
8060             }
8061           else
8062             {
8063               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8064               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8065               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8066               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8067               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8068               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8069               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8070               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8071               const int *idsNodePtr=idsNode->getConstPointer();
8072               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];
8073               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8074               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8075               if(std::abs(norm)>eps)
8076                 {
8077                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8078                   mm3->rotate(center,vec,angle);
8079                 }
8080               mm3->changeSpaceDimension(2);
8081               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8082               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8083               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8084               int nbOfCells=mm4->getNumberOfCells();
8085               for(int k=0;k<nbOfCells;k++)
8086                 {
8087                   int l=0;
8088                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8089                     res->pushBackSilent(idsNodePtr[*work]);
8090                   res->pushBackSilent(-1);
8091                 }
8092             }
8093         }
8094     }
8095   res->popBackSilent();
8096 }
8097
8098 /*!
8099  * 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
8100  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8101  * 
8102  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8103  * \param [in] coords coordinates expected to have 3 components.
8104  * \param [in] begin start of the nodal connectivity of the face.
8105  * \param [in] end end of the nodal connectivity (excluded) of the face.
8106  * \param [out] v the normalized vector of size 3
8107  * \param [out] p the pos of plane
8108  */
8109 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8110 {
8111   std::size_t nbPoints=std::distance(begin,end);
8112   if(nbPoints<3)
8113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8114   double vec[3]={0.,0.,0.};
8115   std::size_t j=0;
8116   bool refFound=false;
8117   for(;j<nbPoints-1 && !refFound;j++)
8118     {
8119       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8120       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8121       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8122       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8123       if(norm>eps)
8124         {
8125           refFound=true;
8126           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8127         }
8128     }
8129   for(std::size_t i=j;i<nbPoints-1;i++)
8130     {
8131       double curVec[3];
8132       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8133       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8134       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8135       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8136       if(norm<eps)
8137         continue;
8138       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8139       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];
8140       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8141       if(norm>eps)
8142         {
8143           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8144           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8145           return ;
8146         }
8147     }
8148   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8149 }
8150
8151 /*!
8152  * This method tries to obtain a well oriented polyhedron.
8153  * If the algorithm fails, an exception will be thrown.
8154  */
8155 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8156 {
8157   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8158   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8159   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8160   isPerm[0]=true;
8161   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8162   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8163   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8164   //
8165   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8166     {
8167       bgFace=begin;
8168       std::size_t smthChanged=0;
8169       for(std::size_t i=0;i<nbOfFaces;i++)
8170         {
8171           endFace=std::find(bgFace+1,end,-1);
8172           nbOfEdgesInFace=std::distance(bgFace,endFace);
8173           if(!isPerm[i])
8174             {
8175               bool b;
8176               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8177                 {
8178                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8179                   std::pair<int,int> p2(p1.second,p1.first);
8180                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8181                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8182                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8183                 }
8184               if(isPerm[i])
8185                 { 
8186                   if(!b)
8187                     std::reverse(bgFace+1,endFace);
8188                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8189                     {
8190                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8191                       std::pair<int,int> p2(p1.second,p1.first);
8192                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8193                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8194                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8195                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8196                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8197                       if(it!=edgesOK.end())
8198                         {
8199                           edgesOK.erase(it);
8200                           edgesFinished.push_back(p1);
8201                         }
8202                       else
8203                         edgesOK.push_back(p1);
8204                     }
8205                 }
8206             }
8207           bgFace=endFace+1;
8208         }
8209       if(smthChanged==0)
8210         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8211     }
8212   if(!edgesOK.empty())
8213     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8214   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8215     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8216       bgFace=begin;
8217       for(std::size_t i=0;i<nbOfFaces;i++)
8218         {
8219           endFace=std::find(bgFace+1,end,-1);
8220           std::reverse(bgFace+1,endFace);
8221           bgFace=endFace+1;
8222         }
8223     }
8224 }
8225
8226 /*!
8227  * This method makes the assumption spacedimension == meshdimension == 2.
8228  * This method works only for linear cells.
8229  * 
8230  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8231  */
8232 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8233 {
8234   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8235     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8236   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8238   int nbOfNodesExpected=m->getNumberOfNodes();
8239   if(m->getNumberOfCells()!=nbOfNodesExpected)
8240     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8242   const int *n2oPtr=n2o->getConstPointer();
8243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8244   m->getReverseNodalConnectivity(revNodal,revNodalI);
8245   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8246   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8247   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8249   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
8250   if(nbOfNodesExpected<1)
8251     return ret.retn();
8252   int prevCell=0;
8253   int prevNode=nodalPtr[nodalIPtr[0]+1];
8254   *work++=n2oPtr[prevNode];
8255   for(int i=1;i<nbOfNodesExpected;i++)
8256     {
8257       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8258         {
8259           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8260           conn.erase(prevNode);
8261           if(conn.size()==1)
8262             {
8263               int curNode=*(conn.begin());
8264               *work++=n2oPtr[curNode];
8265               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8266               shar.erase(prevCell);
8267               if(shar.size()==1)
8268                 {
8269                   prevCell=*(shar.begin());
8270                   prevNode=curNode;
8271                 }
8272               else
8273                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8274             }
8275           else
8276             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8277         }
8278       else
8279         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8280     }
8281   return ret.retn();
8282 }
8283
8284 /*!
8285  * This method makes the assumption spacedimension == meshdimension == 3.
8286  * This method works only for linear cells.
8287  * 
8288  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8289  */
8290 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8291 {
8292   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8293     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8294   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8295   const int *conn=m->getNodalConnectivity()->getConstPointer();
8296   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8297   int nbOfCells=m->getNumberOfCells();
8298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8299   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8300   if(nbOfCells<1)
8301     return ret.retn();
8302   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8303   for(int i=1;i<nbOfCells;i++)
8304     {
8305       *work++=-1;
8306       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8307     }
8308   return ret.retn();
8309 }
8310
8311 /*!
8312  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8313  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8314  */
8315 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8316 {
8317   double *w=zipFrmt;
8318   if(spaceDim==3)
8319     for(int i=0;i<nbOfNodesInCell;i++)
8320       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8321   else if(spaceDim==2)
8322     {
8323       for(int i=0;i<nbOfNodesInCell;i++)
8324         {
8325           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8326           *w++=0.;
8327         }
8328     }
8329   else
8330     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8331 }
8332
8333 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8334 {
8335   int nbOfCells=getNumberOfCells();
8336   if(nbOfCells<=0)
8337     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8338   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,36,4};
8339   ofs << "  <" << getVTKDataSetType() << ">\n";
8340   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8341   ofs << "      <PointData>\n" << pointData << std::endl;
8342   ofs << "      </PointData>\n";
8343   ofs << "      <CellData>\n" << cellData << std::endl;
8344   ofs << "      </CellData>\n";
8345   ofs << "      <Points>\n";
8346   if(getSpaceDimension()==3)
8347     _coords->writeVTK(ofs,8,"Points",byteData);
8348   else
8349     {
8350       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8351       coo->writeVTK(ofs,8,"Points",byteData);
8352     }
8353   ofs << "      </Points>\n";
8354   ofs << "      <Cells>\n";
8355   const int *cPtr=_nodal_connec->getConstPointer();
8356   const int *cIPtr=_nodal_connec_index->getConstPointer();
8357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8361   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8362   int szFaceOffsets=0,szConn=0;
8363   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8364     {
8365       *w2=cPtr[cIPtr[i]];
8366       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8367         {
8368           *w1=-1;
8369           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8370           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8371         }
8372       else
8373         {
8374           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8375           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8376           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8377           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8378           w4=std::copy(c.begin(),c.end(),w4);
8379         }
8380     }
8381   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8382   types->writeVTK(ofs,8,"UInt8","types",byteData);
8383   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8384   if(szFaceOffsets!=0)
8385     {//presence of Polyhedra
8386       connectivity->reAlloc(szConn);
8387       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8388       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8389       w1=faces->getPointer();
8390       for(int i=0;i<nbOfCells;i++)
8391         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8392           {
8393             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8394             *w1++=nbFaces;
8395             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8396             for(int j=0;j<nbFaces;j++)
8397               {
8398                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8399                 *w1++=(int)std::distance(w6,w5);
8400                 w1=std::copy(w6,w5,w1);
8401                 w6=w5+1;
8402               }
8403           }
8404       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8405     }
8406   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8407   ofs << "      </Cells>\n";
8408   ofs << "    </Piece>\n";
8409   ofs << "  </" << getVTKDataSetType() << ">\n";
8410 }
8411
8412 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8413 {
8414   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8415   if(_mesh_dim==-2)
8416     { stream << " Not set !"; return ; }
8417   stream << " Mesh dimension : " << _mesh_dim << ".";
8418   if(_mesh_dim==-1)
8419     return ;
8420   if(!_coords)
8421     { stream << " No coordinates set !"; return ; }
8422   if(!_coords->isAllocated())
8423     { stream << " Coordinates set but not allocated !"; return ; }
8424   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8425   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8426   if(!_nodal_connec_index)
8427     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8428   if(!_nodal_connec_index->isAllocated())
8429     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8430   int lgth=_nodal_connec_index->getNumberOfTuples();
8431   int cpt=_nodal_connec_index->getNumberOfComponents();
8432   if(cpt!=1 || lgth<1)
8433     return ;
8434   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8435 }
8436
8437 std::string MEDCouplingUMesh::getVTKDataSetType() const
8438 {
8439   return std::string("UnstructuredGrid");
8440 }
8441
8442 /*!
8443  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8444  * returns a result mesh constituted by polygons.
8445  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8446  * all nodes from m2.
8447  * The meshes should be in 2D space. In
8448  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8449  * meshes.
8450  *  \param [in] m1 - the first input mesh which is a partitioned object.
8451  *  \param [in] m2 - the second input mesh which is a partition tool.
8452  *  \param [in] eps - precision used to detect coincident mesh entities.
8453  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8454  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8455  *         this array using decrRef() as it is no more needed.
8456  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8457  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8458  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8459  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8460  *         it is no more needed.  
8461  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8462  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8463  *         is no more needed.  
8464  *  \throw If the coordinates array is not set in any of the meshes.
8465  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8466  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8467  */
8468 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8469                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8470 {
8471   m1->checkFullyDefined();
8472   m2->checkFullyDefined();
8473   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8474     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8475
8476   // Step 1: compute all edge intersections (new nodes)
8477   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8478   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8479   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8480   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8481   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8482   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8483   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8484                                       m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8485                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8486   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8487   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8488   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8489
8490   // Step 2: re-order newly created nodes according to the ordering found in m2
8491   std::vector< std::vector<int> > intersectEdge2;
8492   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8493   subDiv2.clear(); dd5=0; dd6=0;
8494
8495   // Step 3:
8496   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8497   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8498   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8499                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8500
8501   // Step 4: Prepare final result:
8502   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8503   addCooDa->alloc((int)(addCoo.size())/2,2);
8504   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8505   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8506   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8507   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8508   std::vector<const DataArrayDouble *> coordss(4);
8509   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8510   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8511   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8512   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8516   ret->setConnectivity(conn,connI,true);
8517   ret->setCoords(coo);
8518   cellNb1=c1.retn(); cellNb2=c2.retn();
8519   return ret.retn();
8520 }
8521
8522
8523 /**
8524  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8525  * (newly created) nodes corresponding to the edge intersections.
8526  * Output params:
8527  * @param[out] cr, crI connectivity of the resulting mesh
8528  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8529  * TODO: describe input parameters
8530  */
8531 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8532                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8533                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8534                                                          const std::vector<double>& addCoords,
8535                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8536 {
8537   static const int SPACEDIM=2;
8538   const double *coo1=m1->getCoords()->getConstPointer();
8539   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8540   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8541   int offset1=m1->getNumberOfNodes();
8542   const double *coo2=m2->getCoords()->getConstPointer();
8543   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8544   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8545   int offset2=offset1+m2->getNumberOfNodes();
8546   int offset3=offset2+((int)addCoords.size())/2;
8547   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8548   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8549   // Here a BBTree on 2D-cells, not on segments:
8550   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8551   int ncell1=m1->getNumberOfCells();
8552   crI.push_back(0);
8553   for(int i=0;i<ncell1;i++)
8554     {
8555       std::vector<int> candidates2;
8556       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8557       std::map<INTERP_KERNEL::Node *,int> mapp;
8558       std::map<int,INTERP_KERNEL::Node *> mappRev;
8559       INTERP_KERNEL::QuadraticPolygon pol1;
8560       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8561       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8562       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8563       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8564       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8565       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8566                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8567       //
8568       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
8569       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8570       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8571       for(it1.first();!it1.finished();it1.next())
8572         edges1.insert(it1.current()->getPtr());
8573       //
8574       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8575       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8576       int ii=0;
8577       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8578         {
8579           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8580           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8581           // Complete mapping with elements coming from the current cell it2 in mesh2:
8582           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8583           // pol2 is the new QP in the final merged result.
8584           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8585                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8586         }
8587       ii=0;
8588       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8589         {
8590           pol1.initLocationsWithOther(pol2s[ii]);
8591           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8592           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8593           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8594         }
8595       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8596       // by m2 but that we still want to keep in the final result.
8597       if(!edges1.empty())
8598         {
8599           try
8600             {
8601               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8602             }
8603           catch(INTERP_KERNEL::Exception& e)
8604             {
8605               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();
8606               throw INTERP_KERNEL::Exception(oss.str().c_str());
8607             }
8608         }
8609       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8610         (*it).second->decrRef();
8611     }
8612 }
8613
8614 /*!
8615  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8616  * It builds the descending connectivity of the two meshes, and then using a binary tree
8617  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
8618  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
8619  */
8620 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8621                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8622                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8623                                                    std::vector<double>& addCoo,
8624                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
8625                                                    throw(INTERP_KERNEL::Exception)
8626 {
8627   static const int SPACEDIM=2;
8628   // Build desc connectivity
8629   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8630   desc2=DataArrayInt::New();
8631   descIndx2=DataArrayInt::New();
8632   revDesc2=DataArrayInt::New();
8633   revDescIndx2=DataArrayInt::New();
8634   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8635   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8636   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8637   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8638   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8639   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8640   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8641
8642   // Build BB tree of all edges in the tool mesh (second mesh)
8643   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8644   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8645   int nDescCell1=m1Desc->getNumberOfCells();
8646   int nDescCell2=m2Desc->getNumberOfCells();
8647   intersectEdge1.resize(nDescCell1);
8648   colinear2.resize(nDescCell2);
8649   subDiv2.resize(nDescCell2);
8650   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8651
8652   std::vector<int> candidates1(1);
8653   int offset1=m1->getNumberOfNodes();
8654   int offset2=offset1+m2->getNumberOfNodes();
8655   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
8656     {
8657       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
8658       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8659       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
8660         {
8661           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8662           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
8663           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8664           candidates1[0]=i;
8665           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8666           // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
8667           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
8668           std::set<INTERP_KERNEL::Node *> nodes;
8669           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
8670           std::size_t szz(nodes.size());
8671           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
8672           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
8673           for(std::size_t iii=0;iii<szz;iii++,itt++)
8674             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
8675           // end of protection
8676           // Performs egde cutting:
8677           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8678           delete pol2;
8679           delete pol1;
8680         }
8681       else
8682         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8683     }
8684   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8685   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8686 }
8687
8688 /*!
8689  * This method performs the 2nd step of Partition of 2D mesh.
8690  * This method has 4 inputs :
8691  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8692  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8693  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
8694  * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2'
8695  * Nodes end up lying consecutively on a cutted edge.
8696  * \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.
8697  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
8698  * \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.
8699  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
8700  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
8701  */
8702 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8703       const std::vector<double>& addCoo,
8704       const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
8705 {
8706   int offset1=m1->getNumberOfNodes();
8707   int ncell=m2->getNumberOfCells();
8708   const int *c=m2->getNodalConnectivity()->getConstPointer();
8709   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8710   const double *coo=m2->getCoords()->getConstPointer();
8711   const double *cooBis=m1->getCoords()->getConstPointer();
8712   int offset2=offset1+m2->getNumberOfNodes();
8713   intersectEdge.resize(ncell);
8714   for(int i=0;i<ncell;i++,cI++)
8715     {
8716       const std::vector<int>& divs=subDiv[i];
8717       int nnode=cI[1]-cI[0]-1;
8718       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8719       std::map<INTERP_KERNEL::Node *, int> mapp22;
8720       for(int j=0;j<nnode;j++)
8721         {
8722           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8723           int nnid=c[(*cI)+j+1];
8724           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8725           mapp22[nn]=nnid+offset1;
8726         }
8727       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8728       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8729         ((*it).second.first)->decrRef();
8730       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8731       std::map<INTERP_KERNEL::Node *,int> mapp3;
8732       for(std::size_t j=0;j<divs.size();j++)
8733         {
8734           int id=divs[j];
8735           INTERP_KERNEL::Node *tmp=0;
8736           if(id<offset1)
8737             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8738           else if(id<offset2)
8739             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8740           else
8741             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8742           addNodes[j]=tmp;
8743           mapp3[tmp]=id;
8744         }
8745       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8746       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8747         (*it)->decrRef();
8748       e->decrRef();
8749     }
8750 }
8751
8752 /*!
8753  * 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).
8754  * 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
8755  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8756  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8757  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8758  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8759  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8760  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8761  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8762  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8763  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8764  * \param [out] cut3DSuf input/output param.
8765  */
8766 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8767                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8768                                                    const int *desc, const int *descIndx, 
8769                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8770 {
8771   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8772   int nbOf3DSurfCell=(int)cut3DSurf.size();
8773   for(int i=0;i<nbOf3DSurfCell;i++)
8774     {
8775       std::vector<int> res;
8776       int offset=descIndx[i];
8777       int nbOfSeg=descIndx[i+1]-offset;
8778       for(int j=0;j<nbOfSeg;j++)
8779         {
8780           int edgeId=desc[offset+j];
8781           int status=cut3DCurve[edgeId];
8782           if(status!=-2)
8783             {
8784               if(status>-1)
8785                 res.push_back(status);
8786               else
8787                 {
8788                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8789                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8790                 }
8791             }
8792         }
8793       switch(res.size())
8794         {
8795         case 2:
8796           {
8797             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8798             break;
8799           }
8800         case 1:
8801         case 0:
8802           {
8803             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8804             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8805             if(res.size()==2)
8806               {
8807                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8808               }
8809             else
8810               {
8811                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8812               }
8813             break;
8814           }
8815         default:
8816           {// case when plane is on a multi colinear edge of a polyhedron
8817             if((int)res.size()==2*nbOfSeg)
8818               {
8819                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8820               }
8821             else
8822               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8823           }
8824         }
8825     }
8826 }
8827
8828 /*!
8829  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8830  * 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).
8831  * 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
8832  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8833  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8834  * \param desc is the descending connectivity 3D->3DSurf
8835  * \param descIndx is the descending connectivity index 3D->3DSurf
8836  */
8837 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8838                                                   const int *desc, const int *descIndx,
8839                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8840 {
8841   checkFullyDefined();
8842   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8843     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8844   const int *nodal3D=_nodal_connec->getConstPointer();
8845   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8846   int nbOfCells=getNumberOfCells();
8847   for(int i=0;i<nbOfCells;i++)
8848     {
8849       std::map<int, std::set<int> > m;
8850       int offset=descIndx[i];
8851       int nbOfFaces=descIndx[i+1]-offset;
8852       int start=-1;
8853       int end=-1;
8854       for(int j=0;j<nbOfFaces;j++)
8855         {
8856           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8857           if(p.first!=-1 && p.second!=-1)
8858             {
8859               if(p.first!=-2)
8860                 {
8861                   start=p.first; end=p.second;
8862                   m[p.first].insert(p.second);
8863                   m[p.second].insert(p.first);
8864                 }
8865               else
8866                 {
8867                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8868                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8869                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8870                   INTERP_KERNEL::NormalizedCellType cmsId;
8871                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8872                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8873                   for(unsigned k=0;k<nbOfNodesSon;k++)
8874                     {
8875                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8876                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8877                     }
8878                 }
8879             }
8880         }
8881       if(m.empty())
8882         continue;
8883       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8884       int prev=end;
8885       while(end!=start)
8886         {
8887           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8888           const std::set<int>& s=(*it).second;
8889           std::set<int> s2; s2.insert(prev);
8890           std::set<int> s3;
8891           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8892           if(s3.size()==1)
8893             {
8894               int val=*s3.begin();
8895               conn.push_back(start);
8896               prev=start;
8897               start=val;
8898             }
8899           else
8900             start=end;
8901         }
8902       conn.push_back(end);
8903       if(conn.size()>3)
8904         {
8905           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8906           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8907           cellIds->pushBackSilent(i);
8908         }
8909     }
8910 }
8911
8912 /*!
8913  * 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
8914  * 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
8915  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8916  * 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
8917  * 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.
8918  * 
8919  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8920  */
8921 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
8922 {
8923   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8924   if(sz>=4)
8925     {
8926       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8927       if(cm.getDimension()==2)
8928         {
8929           const int *node=nodalConnBg+1;
8930           int startNode=*node++;
8931           double refX=coords[2*startNode];
8932           for(;node!=nodalConnEnd;node++)
8933             {
8934               if(coords[2*(*node)]<refX)
8935                 {
8936                   startNode=*node;
8937                   refX=coords[2*startNode];
8938                 }
8939             }
8940           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8941           refX=1e300;
8942           double tmp1;
8943           double tmp2[2];
8944           double angle0=-M_PI/2;
8945           //
8946           int nextNode=-1;
8947           int prevNode=-1;
8948           double resRef;
8949           double angleNext=0.;
8950           while(nextNode!=startNode)
8951             {
8952               nextNode=-1;
8953               resRef=1e300;
8954               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8955                 {
8956                   if(*node!=tmpOut.back() && *node!=prevNode)
8957                     {
8958                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8959                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8960                       double res;
8961                       if(angleM<=angle0)
8962                         res=angle0-angleM;
8963                       else
8964                         res=angle0-angleM+2.*M_PI;
8965                       if(res<resRef)
8966                         {
8967                           nextNode=*node;
8968                           resRef=res;
8969                           angleNext=angleM;
8970                         }
8971                     }
8972                 }
8973               if(nextNode!=startNode)
8974                 {
8975                   angle0=angleNext-M_PI;
8976                   if(angle0<-M_PI)
8977                     angle0+=2*M_PI;
8978                   prevNode=tmpOut.back();
8979                   tmpOut.push_back(nextNode);
8980                 }
8981             }
8982           std::vector<int> tmp3(2*(sz-1));
8983           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8984           std::copy(nodalConnBg+1,nodalConnEnd,it);
8985           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8986             {
8987               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8988               return false;
8989             }
8990           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8991             {
8992               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8993               return false;
8994             }
8995           else
8996             {
8997               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8998               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8999               return true;
9000             }
9001         }
9002       else
9003         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9004     }
9005   else
9006     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9007 }
9008
9009 /*!
9010  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9011  * 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.
9012  * 
9013  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9014  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9015  * \param [in,out] arr array in which the remove operation will be done.
9016  * \param [in,out] arrIndx array in the remove operation will modify
9017  * \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])
9018  * \return true if \b arr and \b arrIndx have been modified, false if not.
9019  */
9020 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9021 {
9022   if(!arrIndx || !arr)
9023     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9024   if(offsetForRemoval<0)
9025     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9026   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9027   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9028   int *arrIPtr=arrIndx->getPointer();
9029   *arrIPtr++=0;
9030   int previousArrI=0;
9031   const int *arrPtr=arr->getConstPointer();
9032   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9033   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9034     {
9035       if(*arrIPtr-previousArrI>offsetForRemoval)
9036         {
9037           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9038             {
9039               if(s.find(*work)==s.end())
9040                 arrOut.push_back(*work);
9041             }
9042         }
9043       previousArrI=*arrIPtr;
9044       *arrIPtr=(int)arrOut.size();
9045     }
9046   if(arr->getNumberOfTuples()==(int)arrOut.size())
9047     return false;
9048   arr->alloc((int)arrOut.size(),1);
9049   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9050   return true;
9051 }
9052
9053 /*!
9054  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9055  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9056  * The selection of extraction is done standardly in new2old format.
9057  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9058  *
9059  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9060  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9061  * \param [in] arrIn arr origin array from which the extraction will be done.
9062  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9063  * \param [out] arrOut the resulting array
9064  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9065  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9066  */
9067 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9068                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9069 {
9070   if(!arrIn || !arrIndxIn)
9071     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9072   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9073   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9074     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9075   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9076   const int *arrInPtr=arrIn->getConstPointer();
9077   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9078   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9079   if(nbOfGrps<0)
9080     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9081   int maxSizeOfArr=arrIn->getNumberOfTuples();
9082   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9083   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9084   arrIo->alloc((int)(sz+1),1);
9085   const int *idsIt=idsOfSelectBg;
9086   int *work=arrIo->getPointer();
9087   *work++=0;
9088   int lgth=0;
9089   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9090     {
9091       if(*idsIt>=0 && *idsIt<nbOfGrps)
9092         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9093       else
9094         {
9095           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9096           throw INTERP_KERNEL::Exception(oss.str().c_str());
9097         }
9098       if(lgth>=work[-1])
9099         *work=lgth;
9100       else
9101         {
9102           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9103           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9104           throw INTERP_KERNEL::Exception(oss.str().c_str());
9105         }
9106     }
9107   arro->alloc(lgth,1);
9108   work=arro->getPointer();
9109   idsIt=idsOfSelectBg;
9110   for(std::size_t i=0;i<sz;i++,idsIt++)
9111     {
9112       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9113         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9114       else
9115         {
9116           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9117           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9118           throw INTERP_KERNEL::Exception(oss.str().c_str());
9119         }
9120     }
9121   arrOut=arro.retn();
9122   arrIndexOut=arrIo.retn();
9123 }
9124
9125 /*!
9126  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9127  * 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 ).
9128  * The selection of extraction is done standardly in new2old format.
9129  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9130  *
9131  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9132  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9133  * \param [in] arrIn arr origin array from which the extraction will be done.
9134  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9135  * \param [out] arrOut the resulting array
9136  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9137  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9138  */
9139 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9140                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9141 {
9142   if(!arrIn || !arrIndxIn)
9143     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9144   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9145   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9146     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9147   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9148   const int *arrInPtr=arrIn->getConstPointer();
9149   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9150   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9151   if(nbOfGrps<0)
9152     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9153   int maxSizeOfArr=arrIn->getNumberOfTuples();
9154   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9155   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9156   arrIo->alloc((int)(sz+1),1);
9157   int idsIt=idsOfSelectStart;
9158   int *work=arrIo->getPointer();
9159   *work++=0;
9160   int lgth=0;
9161   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9162     {
9163       if(idsIt>=0 && idsIt<nbOfGrps)
9164         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9165       else
9166         {
9167           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9168           throw INTERP_KERNEL::Exception(oss.str().c_str());
9169         }
9170       if(lgth>=work[-1])
9171         *work=lgth;
9172       else
9173         {
9174           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9175           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9176           throw INTERP_KERNEL::Exception(oss.str().c_str());
9177         }
9178     }
9179   arro->alloc(lgth,1);
9180   work=arro->getPointer();
9181   idsIt=idsOfSelectStart;
9182   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9183     {
9184       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9185         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9186       else
9187         {
9188           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9189           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9190           throw INTERP_KERNEL::Exception(oss.str().c_str());
9191         }
9192     }
9193   arrOut=arro.retn();
9194   arrIndexOut=arrIo.retn();
9195 }
9196
9197 /*!
9198  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9199  * 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
9200  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9201  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9202  *
9203  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9204  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9205  * \param [in] arrIn arr origin array from which the extraction will be done.
9206  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9207  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9208  * \param [in] srcArrIndex index array of \b srcArr
9209  * \param [out] arrOut the resulting array
9210  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9211  * 
9212  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9213  */
9214 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9215                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9216                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9217 {
9218   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9219     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9220   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9221   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9222   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9223   std::vector<bool> v(nbOfTuples,true);
9224   int offset=0;
9225   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9226   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9227   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9228     {
9229       if(*it>=0 && *it<nbOfTuples)
9230         {
9231           v[*it]=false;
9232           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9233         }
9234       else
9235         {
9236           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9237           throw INTERP_KERNEL::Exception(oss.str().c_str());
9238         }
9239     }
9240   srcArrIndexPtr=srcArrIndex->getConstPointer();
9241   arrIo->alloc(nbOfTuples+1,1);
9242   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9243   const int *arrInPtr=arrIn->getConstPointer();
9244   const int *srcArrPtr=srcArr->getConstPointer();
9245   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9246   int *arroPtr=arro->getPointer();
9247   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9248     {
9249       if(v[ii])
9250         {
9251           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9252           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9253         }
9254       else
9255         {
9256           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9257           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9258           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9259         }
9260     }
9261   arrOut=arro.retn();
9262   arrIndexOut=arrIo.retn();
9263 }
9264
9265 /*!
9266  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9267  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9268  *
9269  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9270  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9271  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9272  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9273  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9274  * \param [in] srcArrIndex index array of \b srcArr
9275  * 
9276  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9277  */
9278 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9279                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9280 {
9281   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9282     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9283   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9284   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9285   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9286   int *arrInOutPtr=arrInOut->getPointer();
9287   const int *srcArrPtr=srcArr->getConstPointer();
9288   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9289     {
9290       if(*it>=0 && *it<nbOfTuples)
9291         {
9292           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9293             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9294           else
9295             {
9296               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] !";
9297               throw INTERP_KERNEL::Exception(oss.str().c_str());
9298             }
9299         }
9300       else
9301         {
9302           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9303           throw INTERP_KERNEL::Exception(oss.str().c_str());
9304         }
9305     }
9306 }
9307
9308 /*!
9309  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9310  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9311  * 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]].
9312  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9313  * A negative value in \b arrIn means that it is ignored.
9314  * 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.
9315  * 
9316  * \param [in] arrIn arr origin array from which the extraction will be done.
9317  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9318  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9319  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9320  */
9321 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9322 {
9323   int seed=0,nbOfDepthPeelingPerformed=0;
9324   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9325 }
9326
9327 /*!
9328  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9329  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9330  * 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]].
9331  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9332  * A negative value in \b arrIn means that it is ignored.
9333  * 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.
9334  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9335  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9336  * \param [in] arrIn arr origin array from which the extraction will be done.
9337  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9338  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9339  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9340  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9341  * \sa MEDCouplingUMesh::partitionBySpreadZone
9342  */
9343 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9344 {
9345   nbOfDepthPeelingPerformed=0;
9346   if(!arrIndxIn)
9347     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9348   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9349   if(nbOfTuples<=0)
9350     {
9351       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9352       return ret;
9353     }
9354   //
9355   std::vector<bool> fetched(nbOfTuples,false);
9356   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9357 }
9358
9359 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9360 {
9361   nbOfDepthPeelingPerformed=0;
9362   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9363     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9364   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9365   std::vector<bool> fetched2(nbOfTuples,false);
9366   int i=0;
9367   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9368     {
9369       if(*seedElt>=0 && *seedElt<nbOfTuples)
9370         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9371       else
9372         { 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()); }
9373     }
9374   const int *arrInPtr=arrIn->getConstPointer();
9375   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9376   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9377   std::vector<int> idsToFetch1(seedBg,seedEnd);
9378   std::vector<int> idsToFetch2;
9379   std::vector<int> *idsToFetch=&idsToFetch1;
9380   std::vector<int> *idsToFetchOther=&idsToFetch2;
9381   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9382     {
9383       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9384         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9385           if(!fetched[*it2])
9386             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9387       std::swap(idsToFetch,idsToFetchOther);
9388       idsToFetchOther->clear();
9389       nbOfDepthPeelingPerformed++;
9390     }
9391   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9392   i=0;
9393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9394   int *retPtr=ret->getPointer();
9395   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9396     if(*it)
9397       *retPtr++=i;
9398   return ret.retn();
9399 }
9400
9401 /*!
9402  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9403  * 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
9404  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9405  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9406  *
9407  * \param [in] start begin of set of ids of the input extraction (included)
9408  * \param [in] end end of set of ids of the input extraction (excluded)
9409  * \param [in] step step of the set of ids in range mode.
9410  * \param [in] arrIn arr origin array from which the extraction will be done.
9411  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9412  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9413  * \param [in] srcArrIndex index array of \b srcArr
9414  * \param [out] arrOut the resulting array
9415  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9416  * 
9417  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9418  */
9419 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9420                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9421                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9422 {
9423   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9424     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9425   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9426   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9427   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9428   int offset=0;
9429   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9430   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9431   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9432   int it=start;
9433   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9434     {
9435       if(it>=0 && it<nbOfTuples)
9436         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9437       else
9438         {
9439           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9440           throw INTERP_KERNEL::Exception(oss.str().c_str());
9441         }
9442     }
9443   srcArrIndexPtr=srcArrIndex->getConstPointer();
9444   arrIo->alloc(nbOfTuples+1,1);
9445   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9446   const int *arrInPtr=arrIn->getConstPointer();
9447   const int *srcArrPtr=srcArr->getConstPointer();
9448   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9449   int *arroPtr=arro->getPointer();
9450   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9451     {
9452       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9453       if(pos<0)
9454         {
9455           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9456           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9457         }
9458       else
9459         {
9460           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9461           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9462         }
9463     }
9464   arrOut=arro.retn();
9465   arrIndexOut=arrIo.retn();
9466 }
9467
9468 /*!
9469  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9470  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9471  *
9472  * \param [in] start begin of set of ids of the input extraction (included)
9473  * \param [in] end end of set of ids of the input extraction (excluded)
9474  * \param [in] step step of the set of ids in range mode.
9475  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9476  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9477  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9478  * \param [in] srcArrIndex index array of \b srcArr
9479  * 
9480  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9481  */
9482 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9483                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9484 {
9485   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9486     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9487   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9488   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9489   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9490   int *arrInOutPtr=arrInOut->getPointer();
9491   const int *srcArrPtr=srcArr->getConstPointer();
9492   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9493   int it=start;
9494   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9495     {
9496       if(it>=0 && it<nbOfTuples)
9497         {
9498           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9499             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9500           else
9501             {
9502               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9503               throw INTERP_KERNEL::Exception(oss.str().c_str());
9504             }
9505         }
9506       else
9507         {
9508           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9509           throw INTERP_KERNEL::Exception(oss.str().c_str());
9510         }
9511     }
9512 }
9513
9514 /*!
9515  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9516  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9517  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9518  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9519  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9520  * 
9521  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9522  */
9523 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9524 {
9525   checkFullyDefined();
9526   int mdim=getMeshDimension();
9527   int spaceDim=getSpaceDimension();
9528   if(mdim!=spaceDim)
9529     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9530   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9531   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9532   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9533   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9534   ret->setCoords(getCoords());
9535   ret->allocateCells((int)partition.size());
9536   //
9537   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9538     {
9539       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9540       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9541       switch(mdim)
9542         {
9543         case 2:
9544           cell=tmp->buildUnionOf2DMesh();
9545           break;
9546         case 3:
9547           cell=tmp->buildUnionOf3DMesh();
9548           break;
9549         default:
9550           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9551         }
9552       
9553       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9554     }
9555   //
9556   ret->finishInsertingCells();
9557   return ret.retn();
9558 }
9559
9560 /*!
9561  * This method partitions \b this into contiguous zone.
9562  * This method only needs a well defined connectivity. Coordinates are not considered here.
9563  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9564  */
9565 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9566 {
9567   int nbOfCellsCur=getNumberOfCells();
9568   std::vector<DataArrayInt *> ret;
9569   if(nbOfCellsCur<=0)
9570     return ret;
9571   DataArrayInt *neigh=0,*neighI=0;
9572   computeNeighborsOfCells(neigh,neighI);
9573   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9574   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9575   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9576   int seed=0;
9577   while(seed<nbOfCellsCur)
9578     {
9579       int nbOfPeelPerformed=0;
9580       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9581       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9582     }
9583   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9584     ret.push_back((*it).retn());
9585   return ret;
9586 }
9587
9588 /*!
9589  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9590  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9591  *
9592  * \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.
9593  * \return a newly allocated DataArrayInt to be managed by the caller.
9594  * \throw In case of \a code has not the right format (typically of size 3*n)
9595  */
9596 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9597 {
9598   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9599   std::size_t nb=code.size()/3;
9600   if(code.size()%3!=0)
9601     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9602   ret->alloc((int)nb,2);
9603   int *retPtr=ret->getPointer();
9604   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9605     {
9606       retPtr[0]=code[3*i+2];
9607       retPtr[1]=code[3*i+2]+code[3*i+1];
9608     }
9609   return ret.retn();
9610 }
9611
9612 /*!
9613  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9614  * All cells in \a this are expected to be linear 3D cells.
9615  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9616  * It leads to an increase to number of cells.
9617  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9618  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
9619  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9620  *
9621  * \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.
9622  *                      For all other cells, the splitting policy will be ignored.
9623  * \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. 
9624  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9625  *          an id of old cell producing it. The caller is to delete this array using
9626  *         decrRef() as it is no more needed.
9627  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9628  *
9629  * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
9630  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
9631  * 
9632  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9633  * \throw If \a this is not fully constituted with linear 3D cells.
9634  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
9635  */
9636 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
9637 {
9638   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9639   checkConnectivityFullyDefined();
9640   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9641     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9642   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9643   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
9644   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9645   int *retPt(ret->getPointer());
9646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9647   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9648   const int *oldc(_nodal_connec->begin());
9649   const int *oldci(_nodal_connec_index->begin());
9650   const double *coords(_coords->begin());
9651   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9652     {
9653       std::vector<int> a; std::vector<double> b;
9654       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9655       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9656       const int *aa(&a[0]);
9657       if(!b.empty())
9658         {
9659           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9660             if(*it<0)
9661               *it=(-(*(it))-1+nbNodes);
9662           addPts->insertAtTheEnd(b.begin(),b.end());
9663           nbNodes+=(int)b.size()/3;
9664         }
9665       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9666         newConn->insertAtTheEnd(aa,aa+4);
9667     }
9668   if(!addPts->empty())
9669     {
9670       addPts->rearrange(3);
9671       nbOfAdditionalPoints=addPts->getNumberOfTuples();
9672       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9673       ret0->setCoords(addPts);
9674     }
9675   else
9676     {
9677       nbOfAdditionalPoints=0;
9678       ret0->setCoords(getCoords());
9679     }
9680   ret0->setNodalConnectivity(newConn);
9681   //
9682   ret->computeOffsets2();
9683   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9684   return ret0.retn();
9685 }
9686
9687 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9688                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9689 {
9690   if(mesh)
9691     {
9692       mesh->incrRef();
9693       _nb_cell=mesh->getNumberOfCells();
9694     }
9695 }
9696
9697 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9698 {
9699   if(_mesh)
9700     _mesh->decrRef();
9701   if(_own_cell)
9702     delete _cell;
9703 }
9704
9705 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9706                                                                                                                                _own_cell(false),_cell_id(bg-1),
9707                                                                                                                                _nb_cell(end)
9708 {
9709   if(mesh)
9710     mesh->incrRef();
9711 }
9712
9713 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9714 {
9715   _cell_id++;
9716   if(_cell_id<_nb_cell)
9717     {
9718       _cell->next();
9719       return _cell;
9720     }
9721   else
9722     return 0;
9723 }
9724
9725 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9726 {
9727   if(_mesh)
9728     _mesh->incrRef();
9729 }
9730
9731 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9732 {
9733   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9734 }
9735
9736 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9737 {
9738   if(_mesh)
9739     _mesh->decrRef();
9740 }
9741
9742 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9743                                                                                                                                                                   _itc(itc),
9744                                                                                                                                                                   _bg(bg),_end(end)
9745 {
9746   if(_mesh)
9747     _mesh->incrRef();
9748 }
9749
9750 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9751 {
9752   if(_mesh)
9753     _mesh->decrRef();
9754 }
9755
9756 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9757 {
9758   return _type;
9759 }
9760
9761 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9762 {
9763   return _end-_bg;
9764 }
9765
9766 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9767 {
9768   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9769 }
9770
9771 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9772 {
9773   if(mesh)
9774     {
9775       mesh->incrRef();
9776       _nb_cell=mesh->getNumberOfCells();
9777     }
9778 }
9779
9780 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9781 {
9782   if(_mesh)
9783     _mesh->decrRef();
9784   delete _cell;
9785 }
9786
9787 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9788 {
9789   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9790   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9791   if(_cell_id<_nb_cell)
9792     {
9793       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9794       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9795       int startId=_cell_id;
9796       _cell_id+=nbOfElems;
9797       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9798     }
9799   else
9800     return 0;
9801 }
9802
9803 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9804 {
9805   if(mesh)
9806     {
9807       _conn=mesh->getNodalConnectivity()->getPointer();
9808       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9809     }
9810 }
9811
9812 void MEDCouplingUMeshCell::next()
9813 {
9814   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9815     {
9816       _conn+=_conn_lgth;
9817       _conn_indx++;
9818     }
9819   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9820 }
9821
9822 std::string MEDCouplingUMeshCell::repr() const
9823 {
9824   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9825     {
9826       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9827       oss << " : ";
9828       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9829       return oss.str();
9830     }
9831   else
9832     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9833 }
9834
9835 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9836 {
9837   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9838     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9839   else
9840     return INTERP_KERNEL::NORM_ERROR;
9841 }
9842
9843 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9844 {
9845   lgth=_conn_lgth;
9846   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9847     return _conn;
9848   else
9849     return 0;
9850 }