Salome HOME
[EDF8478] : Test of read/write of new PENTA18
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2016  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, or (at your option) any later version.
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 (EDF R&D)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCouplingCMesh.hxx"
23 #include "MEDCoupling1GTUMesh.hxx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
30 #include "BBTree.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
44 #include "OrientationInverter.hxx"
45 #include "MEDCouplingUMesh_internal.hxx"
46
47 #include <sstream>
48 #include <fstream>
49 #include <numeric>
50 #include <cstring>
51 #include <limits>
52 #include <list>
53
54 using namespace MEDCoupling;
55
56 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
57
58 /// @cond INTERNAL
59 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_PENTA18, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
60 const int MEDCouplingUMesh::MEDCOUPLING2VTKTYPETRADUCER[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,32,-1,25,42,36,4};
61 /// @endcond
62
63 MEDCouplingUMesh *MEDCouplingUMesh::New()
64 {
65   return new MEDCouplingUMesh;
66 }
67
68 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
69 {
70   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
71   ret->setName(meshName);
72   ret->setMeshDimension(meshDim);
73   return ret;
74 }
75
76 /*!
77  * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
78  * between \a this and the new mesh.
79  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
80  *          delete this mesh using decrRef() as it is no more needed. 
81  */
82 MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const
83 {
84   return clone(true);
85 }
86
87
88 /*!
89  * Returns a new MEDCouplingUMesh which is a copy of \a this one.
90  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
91  * this mesh are shared by the new mesh.
92  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
93  *          delete this mesh using decrRef() as it is no more needed. 
94  */
95 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
96 {
97   return new MEDCouplingUMesh(*this,recDeepCpy);
98 }
99
100 /*!
101  * This method behaves mostly like MEDCouplingUMesh::deepCopy method, except that only nodal connectivity arrays are deeply copied.
102  * The coordinates are shared between \a this and the returned instance.
103  * 
104  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
105  * \sa MEDCouplingUMesh::deepCopy
106  */
107 MEDCouplingUMesh *MEDCouplingUMesh::deepCopyConnectivityOnly() const
108 {
109   checkConnectivityFullyDefined();
110   MCAuto<MEDCouplingUMesh> ret=clone(false);
111   MCAuto<DataArrayInt> c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy());
112   ret->setConnectivity(c,ci);
113   return ret.retn();
114 }
115
116 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
117 {
118   if(!other)
119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
120   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
121   if(!otherC)
122     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
123   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
124   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
125 }
126
127 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
128 {
129   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
130   return ret;
131 }
132
133 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
134 {
135   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
136   ret.push_back(_nodal_connec);
137   ret.push_back(_nodal_connec_index);
138   return ret;
139 }
140
141 void MEDCouplingUMesh::updateTime() const
142 {
143   MEDCouplingPointSet::updateTime();
144   if(_nodal_connec)
145     {
146       updateTimeWith(*_nodal_connec);
147     }
148   if(_nodal_connec_index)
149     {
150       updateTimeWith(*_nodal_connec_index);
151     }
152 }
153
154 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
155 {
156 }
157
158 /*!
159  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
160  * then \a this mesh is most probably is writable, exchangeable and available for most
161  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
162  * this method to check that all is in order with \a this mesh.
163  *  \throw If the mesh dimension is not set.
164  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
165  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
166  *  \throw If the connectivity data array has more than one component.
167  *  \throw If the connectivity data array has a named component.
168  *  \throw If the connectivity index data array has more than one component.
169  *  \throw If the connectivity index data array has a named component.
170  */
171 void MEDCouplingUMesh::checkConsistencyLight() const
172 {
173   if(_mesh_dim<-1)
174     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
175   if(_mesh_dim!=-1)
176     MEDCouplingPointSet::checkConsistencyLight();
177   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
178     {
179       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
180         {
181           std::ostringstream message;
182           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
183           throw INTERP_KERNEL::Exception(message.str().c_str());
184         }
185     }
186   if(_nodal_connec)
187     {
188       if(_nodal_connec->getNumberOfComponents()!=1)
189         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
190       if(_nodal_connec->getInfoOnComponent(0)!="")
191         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
192     }
193   else
194     if(_mesh_dim!=-1)
195       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
196   if(_nodal_connec_index)
197     {
198       if(_nodal_connec_index->getNumberOfComponents()!=1)
199         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
200       if(_nodal_connec_index->getInfoOnComponent(0)!="")
201         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
202     }
203   else
204     if(_mesh_dim!=-1)
205       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
206 }
207
208 /*!
209  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
210  * then \a this mesh is most probably is writable, exchangeable and available for all
211  * algorithms. <br> In addition to the checks performed by checkConsistencyLight(), this
212  * method thoroughly checks the nodal connectivity.
213  *  \param [in] eps - a not used parameter.
214  *  \throw If the mesh dimension is not set.
215  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
216  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
217  *  \throw If the connectivity data array has more than one component.
218  *  \throw If the connectivity data array has a named component.
219  *  \throw If the connectivity index data array has more than one component.
220  *  \throw If the connectivity index data array has a named component.
221  *  \throw If number of nodes defining an element does not correspond to the type of element.
222  *  \throw If the nodal connectivity includes an invalid node id.
223  */
224 void MEDCouplingUMesh::checkConsistency(double eps) const
225 {
226   checkConsistencyLight();
227   if(_mesh_dim==-1)
228     return ;
229   int meshDim=getMeshDimension();
230   int nbOfNodes=getNumberOfNodes();
231   int nbOfCells=getNumberOfCells();
232   const int *ptr=_nodal_connec->getConstPointer();
233   const int *ptrI=_nodal_connec_index->getConstPointer();
234   for(int i=0;i<nbOfCells;i++)
235     {
236       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
237       if((int)cm.getDimension()!=meshDim)
238         {
239           std::ostringstream oss;
240           oss << "MEDCouplingUMesh::checkConsistency : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
241           throw INTERP_KERNEL::Exception(oss.str());
242         }
243       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
244       if(!cm.isDynamic())
245         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
246           {
247             std::ostringstream oss;
248             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
249             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
250             throw INTERP_KERNEL::Exception(oss.str());
251           }
252       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
253         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
254           {
255             std::ostringstream oss;
256             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
257             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
258             throw INTERP_KERNEL::Exception(oss.str());
259           }
260       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
261         {
262           int nodeId=*w;
263           if(nodeId>=0)
264             {
265               if(nodeId>=nbOfNodes)
266                 {
267                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
268                   throw INTERP_KERNEL::Exception(oss.str());
269                 }
270             }
271           else if(nodeId<-1)
272             {
273               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
274               throw INTERP_KERNEL::Exception(oss.str());
275             }
276           else
277             {
278               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
279                 {
280                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
281                   throw INTERP_KERNEL::Exception(oss.str());
282                 }
283             }
284         }
285     }
286 }
287
288 /*!
289  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
290  * elements contained in the mesh. For more info on the mesh dimension see
291  * \ref MEDCouplingUMeshPage.
292  *  \param [in] meshDim - a new mesh dimension.
293  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
294  */
295 void MEDCouplingUMesh::setMeshDimension(int meshDim)
296 {
297   if(meshDim<-1 || meshDim>3)
298     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
299   _mesh_dim=meshDim;
300   declareAsNew();
301 }
302
303 /*!
304  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
305  * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
306  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
307  *
308  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
309  *
310  *  \if ENABLE_EXAMPLES
311  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
312  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
313  *  \endif
314  */
315 void MEDCouplingUMesh::allocateCells(int nbOfCells)
316 {
317   if(nbOfCells<0)
318     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
319   if(_nodal_connec_index)
320     {
321       _nodal_connec_index->decrRef();
322     }
323   if(_nodal_connec)
324     {
325       _nodal_connec->decrRef();
326     }
327   _nodal_connec_index=DataArrayInt::New();
328   _nodal_connec_index->reserve(nbOfCells+1);
329   _nodal_connec_index->pushBackSilent(0);
330   _nodal_connec=DataArrayInt::New();
331   _nodal_connec->reserve(2*nbOfCells);
332   _types.clear();
333   declareAsNew();
334 }
335
336 /*!
337  * Appends a cell to the connectivity array. For deeper understanding what is
338  * happening see \ref MEDCouplingUMeshNodalConnectivity.
339  *  \param [in] type - type of cell to add.
340  *  \param [in] size - number of nodes constituting this cell.
341  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
342  * 
343  *  \if ENABLE_EXAMPLES
344  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
345  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
346  *  \endif
347  */
348 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
349 {
350   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
351   if(_nodal_connec_index==0)
352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
353   if((int)cm.getDimension()==_mesh_dim)
354     {
355       if(!cm.isDynamic())
356         if(size!=(int)cm.getNumberOfNodes())
357           {
358             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
359             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
360             throw INTERP_KERNEL::Exception(oss.str());
361           }
362       int idx=_nodal_connec_index->back();
363       int val=idx+size+1;
364       _nodal_connec_index->pushBackSilent(val);
365       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
366       _types.insert(type);
367     }
368   else
369     {
370       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
371       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
372       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
373       throw INTERP_KERNEL::Exception(oss.str());
374     }
375 }
376
377 /*!
378  * Compacts data arrays to release unused memory. This method is to be called after
379  * finishing cell insertion using \a this->insertNextCell().
380  * 
381  *  \if ENABLE_EXAMPLES
382  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
383  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
384  *  \endif
385  */
386 void MEDCouplingUMesh::finishInsertingCells()
387 {
388   _nodal_connec->pack();
389   _nodal_connec_index->pack();
390   _nodal_connec->declareAsNew();
391   _nodal_connec_index->declareAsNew();
392   updateTime();
393 }
394
395 /*!
396  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
397  * Useful for python users.
398  */
399 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
400 {
401   return new MEDCouplingUMeshCellIterator(this);
402 }
403
404 /*!
405  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
406  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
407  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
408  * Useful for python users.
409  */
410 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
411 {
412   if(!checkConsecutiveCellTypes())
413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
414   return new MEDCouplingUMeshCellByTypeEntry(this);
415 }
416
417 /*!
418  * Returns a set of all cell types available in \a this mesh.
419  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
420  * \warning this method does not throw any exception even if \a this is not defined.
421  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
422  */
423 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
424 {
425   return _types;
426 }
427
428 /*!
429  * This method returns the sorted list of geometric types in \a this.
430  * 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
431  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
432  *
433  * \throw if connectivity in \a this is not correctly defined.
434  *  
435  * \sa MEDCouplingMesh::getAllGeoTypes
436  */
437 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
438 {
439   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
440   checkConnectivityFullyDefined();
441   int nbOfCells(getNumberOfCells());
442   if(nbOfCells==0)
443     return ret;
444   if(getNodalConnectivityArrayLen()<1)
445     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
446   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
447   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
448   for(int i=1;i<nbOfCells;i++,ci++)
449     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
450       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
451   return ret;
452 }
453
454 /*!
455  * This method is a method that compares \a this and \a other.
456  * This method compares \b all attributes, even names and component names.
457  */
458 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
459 {
460   if(!other)
461     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
462   std::ostringstream oss; oss.precision(15);
463   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
464   if(!otherC)
465     {
466       reason="mesh given in input is not castable in MEDCouplingUMesh !";
467       return false;
468     }
469   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
470     return false;
471   if(_mesh_dim!=otherC->_mesh_dim)
472     {
473       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
474       reason=oss.str();
475       return false;
476     }
477   if(_types!=otherC->_types)
478     {
479       oss << "umesh geometric type mismatch :\nThis geometric types are :";
480       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
481         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
482       oss << "\nOther geometric types are :";
483       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
484         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
485       reason=oss.str();
486       return false;
487     }
488   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
489     if(_nodal_connec==0 || otherC->_nodal_connec==0)
490       {
491         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
492         return false;
493       }
494   if(_nodal_connec!=otherC->_nodal_connec)
495     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
496       {
497         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
498         return false;
499       }
500   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
501     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
502       {
503         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
504         return false;
505       }
506   if(_nodal_connec_index!=otherC->_nodal_connec_index)
507     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
508       {
509         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
510         return false;
511       }
512   return true;
513 }
514
515 /*!
516  * Checks if data arrays of this mesh (node coordinates, nodal
517  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
518  * not considered.
519  *  \param [in] other - the mesh to compare with.
520  *  \param [in] prec - precision value used to compare node coordinates.
521  *  \return bool - \a true if the two meshes are same.
522  */
523 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
524 {
525   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
526   if(!otherC)
527     return false;
528   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
529     return false;
530   if(_mesh_dim!=otherC->_mesh_dim)
531     return false;
532   if(_types!=otherC->_types)
533     return false;
534   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
535     if(_nodal_connec==0 || otherC->_nodal_connec==0)
536       return false;
537   if(_nodal_connec!=otherC->_nodal_connec)
538     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
539       return false;
540   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
541     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
542       return false;
543   if(_nodal_connec_index!=otherC->_nodal_connec_index)
544     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
545       return false;
546   return true;
547 }
548
549 /*!
550  * Checks if \a this and \a other meshes are geometrically equivalent with high
551  * probability, else an exception is thrown. The meshes are considered equivalent if
552  * (1) meshes contain the same number of nodes and the same number of elements of the
553  * same types (2) three cells of the two meshes (first, last and middle) are based
554  * on coincident nodes (with a specified precision).
555  *  \param [in] other - the mesh to compare with.
556  *  \param [in] prec - the precision used to compare nodes of the two meshes.
557  *  \throw If the two meshes do not match.
558  */
559 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
560 {
561   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
562   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
563   if(!otherC)
564     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
565 }
566
567 /*!
568  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
569  * cells each node belongs to.
570  * \warning For speed reasons, this method does not check if node ids in the nodal
571  *          connectivity correspond to the size of node coordinates array.
572  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
573  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
574  *        dividing cell ids in \a revNodal into groups each referring to one
575  *        node. Its every element (except the last one) is an index pointing to the
576  *         first id of a group of cells. For example cells sharing the node #1 are 
577  *        described by following range of indices: 
578  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
579  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
580  *        Number of cells sharing the *i*-th node is
581  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
582  * \throw If the coordinates array is not set.
583  * \throw If the nodal connectivity of cells is not defined.
584  * 
585  * \if ENABLE_EXAMPLES
586  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
587  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
588  * \endif
589  */
590 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
591 {
592   checkFullyDefined();
593   int nbOfNodes(getNumberOfNodes());
594   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
595   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
596   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
597   const int *conn(_nodal_connec->begin()),*connIndex(_nodal_connec_index->begin());
598   int nbOfCells(getNumberOfCells()),nbOfEltsInRevNodal(0);
599   for(int eltId=0;eltId<nbOfCells;eltId++)
600     {
601       const int *strtNdlConnOfCurCell(conn+connIndex[eltId]+1),*endNdlConnOfCurCell(conn+connIndex[eltId+1]);
602       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
603         if(*iter>=0)//for polyhedrons
604           {
605             nbOfEltsInRevNodal++;
606             revNodalIndxPtr[(*iter)+1]++;
607           }
608     }
609   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
610   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
611   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
612   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
613   for(int eltId=0;eltId<nbOfCells;eltId++)
614     {
615       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
616       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
617       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
618         if(*iter>=0)//for polyhedrons
619           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
620     }
621 }
622
623 /*!
624  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
625  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
626  * describing correspondence between cells of \a this and the result meshes are
627  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
628  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
629  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
630  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
631  * \warning For speed reasons, this method does not check if node ids in the nodal
632  *          connectivity correspond to the size of node coordinates array.
633  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
634  *          to write this mesh to the MED file, its cells must be sorted using
635  *          sortCellsInMEDFileFrmt().
636  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
637  *         each cell of \a this mesh.
638  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
639  *        dividing cell ids in \a desc into groups each referring to one
640  *        cell of \a this mesh. Its every element (except the last one) is an index
641  *        pointing to the first id of a group of cells. For example cells of the
642  *        result mesh bounding the cell #1 of \a this mesh are described by following
643  *        range of indices:
644  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
645  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
646  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
647  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
648  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
649  *         by each cell of the result mesh.
650  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
651  *        in the result mesh,
652  *        dividing cell ids in \a revDesc into groups each referring to one
653  *        cell of the result mesh the same way as \a descIndx divides \a desc.
654  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
655  *        delete this mesh using decrRef() as it is no more needed.
656  *  \throw If the coordinates array is not set.
657  *  \throw If the nodal connectivity of cells is node defined.
658  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
659  *         revDescIndx == NULL.
660  * 
661  *  \if ENABLE_EXAMPLES
662  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
663  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
664  *  \endif
665  * \sa buildDescendingConnectivity2()
666  */
667 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
668 {
669   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
670 }
671
672 /*!
673  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
674  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
675  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
676  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
677  * \sa MEDCouplingUMesh::buildDescendingConnectivity
678  */
679 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
680 {
681   checkFullyDefined();
682   if(getMeshDimension()!=3)
683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
684   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
685 }
686
687 /*!
688  * This method computes the micro edges constituting each cell in \a this. Micro edge is an edge for non quadratic cells. Micro edge is an half edge for quadratic cells.
689  * This method works for both meshes with mesh dimenstion equal to 2 or 3. Dynamical cells are not supported (polygons, polyhedrons...)
690  * 
691  * \sa explode3DMeshTo1D, buildDescendingConnectiviy
692  */
693 MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
694 {
695    checkFullyDefined();
696    switch(getMeshDimension())
697      {
698      case 2:
699        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
700      case 3:
701        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
702      default:
703        throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explodeMeshIntoMicroEdges : Only 2D and 3D supported !");
704      }
705 }
706
707 /*!
708  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
709  * this->getMeshDimension(), that bound cells of \a this mesh. In
710  * addition arrays describing correspondence between cells of \a this and the result
711  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
712  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
713  *  mesh. This method differs from buildDescendingConnectivity() in that apart
714  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
715  * result meshes. So a positive id means that order of nodes in corresponding cells
716  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
717  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
718  * i.e. cell ids are one-based.
719  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
720  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
721  * \warning For speed reasons, this method does not check if node ids in the nodal
722  *          connectivity correspond to the size of node coordinates array.
723  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
724  *          to write this mesh to the MED file, its cells must be sorted using
725  *          sortCellsInMEDFileFrmt().
726  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
727  *         each cell of \a this mesh.
728  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
729  *        dividing cell ids in \a desc into groups each referring to one
730  *        cell of \a this mesh. Its every element (except the last one) is an index
731  *        pointing to the first id of a group of cells. For example cells of the
732  *        result mesh bounding the cell #1 of \a this mesh are described by following
733  *        range of indices:
734  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
735  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
736  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
737  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
738  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
739  *         by each cell of the result mesh.
740  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
741  *        in the result mesh,
742  *        dividing cell ids in \a revDesc into groups each referring to one
743  *        cell of the result mesh the same way as \a descIndx divides \a desc.
744  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
745  *        shares the node coordinates array with \a this mesh. The caller is to
746  *        delete this mesh using decrRef() as it is no more needed.
747  *  \throw If the coordinates array is not set.
748  *  \throw If the nodal connectivity of cells is node defined.
749  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
750  *         revDescIndx == NULL.
751  * 
752  *  \if ENABLE_EXAMPLES
753  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
754  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
755  *  \endif
756  * \sa buildDescendingConnectivity()
757  */
758 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
759 {
760   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
761 }
762
763 /*!
764  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
765  * For speed reasons no check of this will be done. This method calls
766  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
767  * This method lists cell by cell in \b this which are its neighbors. To compute the result
768  * only connectivities are considered.
769  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
770  * The format of return is hence \ref numbering-indirect.
771  *
772  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
773  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
774  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
775  * is equal to the last values in \b neighborsIndx.
776  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
777  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
778  */
779 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
780 {
781   MCAuto<DataArrayInt> desc=DataArrayInt::New();
782   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
783   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
784   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
785   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
786   meshDM1=0;
787   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
788 }
789
790 void MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne(const DataArrayInt *nodeNeigh, const DataArrayInt *nodeNeighI, MCAuto<DataArrayInt>& cellNeigh, MCAuto<DataArrayInt>& cellNeighIndex) const
791 {
792   if(!nodeNeigh || !nodeNeighI)
793     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : null pointer !");
794   checkConsistencyLight();
795   nodeNeigh->checkAllocated(); nodeNeighI->checkAllocated();
796   nodeNeigh->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh");
797   nodeNeighI->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh index");
798   nodeNeighI->checkNbOfTuples(1+getNumberOfNodes(),"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : invalid length");
799   int nbCells(getNumberOfCells());
800   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin()),*ne(nodeNeigh->begin()),*nei(nodeNeighI->begin());
801   cellNeigh=DataArrayInt::New(); cellNeigh->alloc(0,1); cellNeighIndex=DataArrayInt::New(); cellNeighIndex->alloc(1,1); cellNeighIndex->setIJ(0,0,0);
802   for(int i=0;i<nbCells;i++)
803     {
804       std::set<int> s;
805       for(const int *it=c+ci[i]+1;it!=c+ci[i+1];it++)
806         if(*it>=0)
807           s.insert(ne+nei[*it],ne+nei[*it+1]);
808       s.erase(i);
809       cellNeigh->insertAtTheEnd(s.begin(),s.end());
810       cellNeighIndex->pushBackSilent(cellNeigh->getNumberOfTuples());
811     }
812 }
813
814 /*!
815  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
816  * of MEDCouplingUMesh::computeNeighborsOfCells.
817  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
818  * typically the case to extract a set a neighbours,
819  * excluding a set of meshdim-1 cells in input descending connectivity.
820  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
821  * 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
823  * are considered.
824  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
825  *
826  * \param [in] desc descending connectivity array.
827  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
828  * \param [in] revDesc reverse descending connectivity array.
829  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
830  * \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
831  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
832  * \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.
833  */
834 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
835                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
836 {
837   if(!desc || !descIndx || !revDesc || !revDescIndx)
838     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
839   const int *descPtr=desc->begin();
840   const int *descIPtr=descIndx->begin();
841   const int *revDescPtr=revDesc->begin();
842   const int *revDescIPtr=revDescIndx->begin();
843   //
844   int nbCells=descIndx->getNumberOfTuples()-1;
845   MCAuto<DataArrayInt> out0=DataArrayInt::New();
846   MCAuto<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
847   int *out1Ptr=out1->getPointer();
848   *out1Ptr++=0;
849   out0->reserve(desc->getNumberOfTuples());
850   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
851     {
852       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
853         {
854           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
855           s.erase(i);
856           out0->insertAtTheEnd(s.begin(),s.end());
857         }
858       *out1Ptr=out0->getNumberOfTuples();
859     }
860   neighbors=out0.retn();
861   neighborsIndx=out1.retn();
862 }
863
864 /*!
865  * Explodes \a this into edges whatever its dimension.
866  */
867 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::explodeIntoEdges(MCAuto<DataArrayInt>& desc, MCAuto<DataArrayInt>& descIndex, MCAuto<DataArrayInt>& revDesc, MCAuto<DataArrayInt>& revDescIndx) const
868 {
869   checkFullyDefined();
870   int mdim(getMeshDimension());
871   desc=DataArrayInt::New(); descIndex=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
872   MCAuto<MEDCouplingUMesh> mesh1D;
873   switch(mdim)
874   {
875     case 3:
876       {
877         mesh1D=explode3DMeshTo1D(desc,descIndex,revDesc,revDescIndx);
878         break;
879       }
880     case 2:
881       {
882         mesh1D=buildDescendingConnectivity(desc,descIndex,revDesc,revDescIndx);
883         break;
884       }
885     default:
886       {
887         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2] !");
888       }
889   }
890   return mesh1D;
891 }
892
893 /*!
894  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
895  * For speed reasons no check of this will be done. This method calls
896  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
897  * This method lists node by node in \b this which are its neighbors. To compute the result
898  * only connectivities are considered.
899  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
900  *
901  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
902  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
903  * parameter allows to select the right part in this array (\ref numbering-indirect).
904  * The number of tuples is equal to the last values in \b neighborsIndx.
905  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
906  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
907  * 
908  * \sa MEDCouplingUMesh::computeEnlargedNeighborsOfNodes
909  */
910 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
911 {
912   checkFullyDefined();
913   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
914   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
915   MCConstAuto<MEDCouplingUMesh> mesh1D;
916   switch(mdim)
917   {
918     case 3:
919       {
920         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
921         break;
922       }
923     case 2:
924       {
925         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
926         break;
927       }
928     case 1:
929       {
930         mesh1D.takeRef(this);
931         break;
932       }
933     default:
934       {
935         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
936       }
937   }
938   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
939   mesh1D->getReverseNodalConnectivity(desc,descIndx);
940   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
941   ret0->alloc(desc->getNumberOfTuples(),1);
942   int *r0Pt(ret0->getPointer());
943   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
944   for(int i=0;i<nbNodes;i++,rni++)
945     {
946       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
947         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
948     }
949   neighbors=ret0.retn();
950   neighborsIdx=descIndx.retn();
951 }
952
953 /*!
954  * Computes enlarged neighbors for each nodes in \a this. The behavior of this method is close to MEDCouplingUMesh::computeNeighborsOfNodes except that the neighborhood of each node is wider here.
955  * A node j is considered to be in the neighborhood of i if and only if there is a cell in \a this containing in its nodal connectivity both i and j.
956  * This method is useful to find ghost cells of a part of a mesh with a code based on fields on nodes.
957  * 
958  * \sa MEDCouplingUMesh::computeNeighborsOfNodes
959  */
960 void MEDCouplingUMesh::computeEnlargedNeighborsOfNodes(MCAuto<DataArrayInt> &neighbors, MCAuto<DataArrayInt>& neighborsIdx) const
961 {
962   checkFullyDefined();
963   int nbOfNodes(getNumberOfNodes());
964   const int *conn(_nodal_connec->begin()),*connIndex(_nodal_connec_index->begin());
965   int nbOfCells(getNumberOfCells());
966   std::vector< std::set<int> > st0(nbOfNodes);
967   for(int eltId=0;eltId<nbOfCells;eltId++)
968     {
969       const int *strtNdlConnOfCurCell(conn+connIndex[eltId]+1),*endNdlConnOfCurCell(conn+connIndex[eltId+1]);
970       std::set<int> s(strtNdlConnOfCurCell,endNdlConnOfCurCell); s.erase(-1); //for polyhedrons
971       for(std::set<int>::const_iterator iter2=s.begin();iter2!=s.end();iter2++)
972         st0[*iter2].insert(s.begin(),s.end());
973     }
974   neighborsIdx=DataArrayInt::New(); neighborsIdx->alloc(nbOfNodes+1,1); neighborsIdx->setIJ(0,0,0);
975   {
976     int *neighIdx(neighborsIdx->getPointer());
977     for(std::vector< std::set<int> >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++)
978       neighIdx[1]=neighIdx[0]+(*it).size()-1;
979   }
980   neighbors=DataArrayInt::New(); neighbors->alloc(neighborsIdx->back(),1);
981   {
982     const int *neighIdx(neighborsIdx->begin());
983     int *neigh(neighbors->getPointer()),nodeId(0);
984     for(std::vector< std::set<int> >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++,nodeId++)
985       {
986         std::set<int> s(*it); s.erase(nodeId);
987         std::copy(s.begin(),s.end(),neigh+*neighIdx);
988       }
989   }
990 }
991
992 /*!
993  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
994  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
995  * array of cell ids. Pay attention that after conversion all algorithms work slower
996  * with \a this mesh than before conversion. <br> If an exception is thrown during the
997  * conversion due presence of invalid ids in the array of cells to convert, as a
998  * result \a this mesh contains some already converted elements. In this case the 2D
999  * mesh remains valid but 3D mesh becomes \b inconsistent!
1000  *  \warning This method can significantly modify the order of geometric types in \a this,
1001  *          hence, to write this mesh to the MED file, its cells must be sorted using
1002  *          sortCellsInMEDFileFrmt().
1003  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1004  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1005  *         cellIdsToConvertBg.
1006  *  \throw If the coordinates array is not set.
1007  *  \throw If the nodal connectivity of cells is node defined.
1008  *  \throw If dimension of \a this mesh is not either 2 or 3.
1009  *
1010  *  \if ENABLE_EXAMPLES
1011  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1012  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1013  *  \endif
1014  */
1015 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1016 {
1017   checkFullyDefined();
1018   int dim=getMeshDimension();
1019   if(dim<2 || dim>3)
1020     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1021   int nbOfCells(getNumberOfCells());
1022   if(dim==2)
1023     {
1024       const int *connIndex=_nodal_connec_index->begin();
1025       int *conn=_nodal_connec->getPointer();
1026       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1027         {
1028           if(*iter>=0 && *iter<nbOfCells)
1029             {
1030               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1031               if(!cm.isQuadratic())
1032                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1033               else
1034                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1035             }
1036           else
1037             {
1038               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1039               oss << " in range [0," << nbOfCells << ") !";
1040               throw INTERP_KERNEL::Exception(oss.str());
1041             }
1042         }
1043     }
1044   else
1045     {
1046       int *connIndex(_nodal_connec_index->getPointer());
1047       const int *connOld(_nodal_connec->getConstPointer());
1048       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1049       std::vector<bool> toBeDone(nbOfCells,false);
1050       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1051         {
1052           if(*iter>=0 && *iter<nbOfCells)
1053             toBeDone[*iter]=true;
1054           else
1055             {
1056               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1057               oss << " in range [0," << nbOfCells << ") !";
1058               throw INTERP_KERNEL::Exception(oss.str());
1059             }
1060         }
1061       for(int cellId=0;cellId<nbOfCells;cellId++)
1062         {
1063           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1064           int lgthOld(posP1-pos-1);
1065           if(toBeDone[cellId])
1066             {
1067               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1068               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1069               int *tmp(new int[nbOfFaces*lgthOld+1]);
1070               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1071               for(unsigned j=0;j<nbOfFaces;j++)
1072                 {
1073                   INTERP_KERNEL::NormalizedCellType type;
1074                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1075                   work+=offset;
1076                   *work++=-1;
1077                 }
1078               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1079               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1080               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1081               delete [] tmp;
1082             }
1083           else
1084             {
1085               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1086               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1087             }
1088         }
1089       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1090     }
1091   computeTypes();
1092 }
1093
1094 /*!
1095  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1096  * polyhedrons (if \a this is a 3D mesh).
1097  *  \warning As this method is purely for user-friendliness and no optimization is
1098  *          done to avoid construction of a useless vector, this method can be costly
1099  *          in memory.
1100  *  \throw If the coordinates array is not set.
1101  *  \throw If the nodal connectivity of cells is node defined.
1102  *  \throw If dimension of \a this mesh is not either 2 or 3.
1103  */
1104 void MEDCouplingUMesh::convertAllToPoly()
1105 {
1106   int nbOfCells=getNumberOfCells();
1107   std::vector<int> cellIds(nbOfCells);
1108   for(int i=0;i<nbOfCells;i++)
1109     cellIds[i]=i;
1110   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1111 }
1112
1113 /*!
1114  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1115  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1116  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1117  * base facet of the volume and the second half of nodes describes an opposite facet
1118  * having the same number of nodes as the base one. This method converts such
1119  * connectivity to a valid polyhedral format where connectivity of each facet is
1120  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1121  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1122  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1123  * a correct orientation of the first facet of a polyhedron, else orientation of a
1124  * corrected cell is reverse.<br>
1125  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1126  * it releases the user from boring description of polyhedra connectivity in the valid
1127  * format.
1128  *  \throw If \a this->getMeshDimension() != 3.
1129  *  \throw If \a this->getSpaceDimension() != 3.
1130  *  \throw If the nodal connectivity of cells is not defined.
1131  *  \throw If the coordinates array is not set.
1132  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1133  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1134  *
1135  *  \if ENABLE_EXAMPLES
1136  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1137  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1138  *  \endif
1139  */
1140 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1141 {
1142   checkFullyDefined();
1143   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1144     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1145   int nbOfCells=getNumberOfCells();
1146   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1147   newCi->alloc(nbOfCells+1,1);
1148   int *newci=newCi->getPointer();
1149   const int *ci=_nodal_connec_index->getConstPointer();
1150   const int *c=_nodal_connec->getConstPointer();
1151   newci[0]=0;
1152   for(int i=0;i<nbOfCells;i++)
1153     {
1154       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1155       if(type==INTERP_KERNEL::NORM_POLYHED)
1156         {
1157           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1158             {
1159               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1160               throw INTERP_KERNEL::Exception(oss.str());
1161             }
1162           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1163           if(n2%2!=0)
1164             {
1165               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 !";
1166               throw INTERP_KERNEL::Exception(oss.str());
1167             }
1168           int n1=(int)(n2/2);
1169           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)
1170         }
1171       else
1172         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1173     }
1174   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1175   newC->alloc(newci[nbOfCells],1);
1176   int *newc=newC->getPointer();
1177   for(int i=0;i<nbOfCells;i++)
1178     {
1179       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1180       if(type==INTERP_KERNEL::NORM_POLYHED)
1181         {
1182           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1183           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1184           *newc++=-1;
1185           for(std::size_t j=0;j<n1;j++)
1186             {
1187               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1188               newc[n1+5*j]=-1;
1189               newc[n1+5*j+1]=c[ci[i]+1+j];
1190               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1191               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1192               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1193             }
1194           newc+=n1*6;
1195         }
1196       else
1197         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1198     }
1199   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1200   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1201 }
1202
1203
1204 /*!
1205  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1206  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1207  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1208  *          to write this mesh to the MED file, its cells must be sorted using
1209  *          sortCellsInMEDFileFrmt().
1210  * \warning Cells (and most notably polyhedrons) must be correctly oriented for this to work
1211  *          properly. See orientCorrectlyPolyhedrons() and arePolyhedronsNotCorrectlyOriented().
1212  * \return \c true if at least one cell has been converted, \c false else. In the
1213  *         last case the nodal connectivity remains unchanged.
1214  * \throw If the coordinates array is not set.
1215  * \throw If the nodal connectivity of cells is not defined.
1216  * \throw If \a this->getMeshDimension() < 0.
1217  */
1218 bool MEDCouplingUMesh::unPolyze()
1219 {
1220   checkFullyDefined();
1221   int mdim=getMeshDimension();
1222   if(mdim<0)
1223     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1224   if(mdim<=1)
1225     return false;
1226   int nbOfCells=getNumberOfCells();
1227   if(nbOfCells<1)
1228     return false;
1229   int initMeshLgth=getNodalConnectivityArrayLen();
1230   int *conn=_nodal_connec->getPointer();
1231   int *index=_nodal_connec_index->getPointer();
1232   int posOfCurCell=0;
1233   int newPos=0;
1234   int lgthOfCurCell;
1235   bool ret=false;
1236   for(int i=0;i<nbOfCells;i++)
1237     {
1238       lgthOfCurCell=index[i+1]-posOfCurCell;
1239       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1240       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1241       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1242       int newLgth;
1243       if(cm.isDynamic())
1244         {
1245           switch(cm.getDimension())
1246           {
1247             case 2:
1248               {
1249                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1250                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1251                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1252                 break;
1253               }
1254             case 3:
1255               {
1256                 int nbOfFaces,lgthOfPolyhConn;
1257                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1258                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1259                 break;
1260               }
1261             case 1:
1262               {
1263                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1264                 break;
1265               }
1266           }
1267           ret=ret || (newType!=type);
1268           conn[newPos]=newType;
1269           newPos+=newLgth+1;
1270           posOfCurCell=index[i+1];
1271           index[i+1]=newPos;
1272         }
1273       else
1274         {
1275           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1276           newPos+=lgthOfCurCell;
1277           posOfCurCell+=lgthOfCurCell;
1278           index[i+1]=newPos;
1279         }
1280     }
1281   if(newPos!=initMeshLgth)
1282     _nodal_connec->reAlloc(newPos);
1283   if(ret)
1284     computeTypes();
1285   return ret;
1286 }
1287
1288 /*!
1289  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1290  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1291  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1292  *
1293  * \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 
1294  *             precision.
1295  */
1296 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1297 {
1298   checkFullyDefined();
1299   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1300     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1301   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1302   coords->recenterForMaxPrecision(eps);
1303   //
1304   int nbOfCells=getNumberOfCells();
1305   const int *conn=_nodal_connec->getConstPointer();
1306   const int *index=_nodal_connec_index->getConstPointer();
1307   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1308   connINew->alloc(nbOfCells+1,1);
1309   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1310   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1311   bool changed=false;
1312   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1313     {
1314       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1315         {
1316           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1317           changed=true;
1318         }
1319       else
1320         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1321       *connINewPtr=connNew->getNumberOfTuples();
1322     }
1323   if(changed)
1324     setConnectivity(connNew,connINew,false);
1325 }
1326
1327 /*!
1328  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1329  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1330  * the format of the returned DataArrayInt instance.
1331  * 
1332  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1333  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1334  */
1335 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1336 {
1337   checkConnectivityFullyDefined();
1338   const int *maxEltPt(std::max_element(_nodal_connec->begin(),_nodal_connec->end()));
1339   int maxElt(maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1);
1340   std::vector<bool> retS(maxElt,false);
1341   computeNodeIdsAlg(retS);
1342   return DataArrayInt::BuildListOfSwitchedOn(retS);
1343 }
1344
1345 /*!
1346  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1347  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1348  */
1349 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1350 {
1351   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1352   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1353   for(int i=0;i<nbOfCells;i++)
1354     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1355       if(conn[j]>=0)
1356         {
1357           if(conn[j]<nbOfNodes)
1358             nodeIdsInUse[conn[j]]=true;
1359           else
1360             {
1361               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1362               throw INTERP_KERNEL::Exception(oss.str());
1363             }
1364         }
1365 }
1366
1367 /// @cond INTERNAL
1368
1369 struct MEDCouplingAccVisit
1370 {
1371   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1372   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1373   int _new_nb_of_nodes;
1374 };
1375
1376 /// @endcond
1377
1378 /*!
1379  * Finds nodes not used in any cell and returns an array giving a new id to every node
1380  * by excluding the unused nodes, for which the array holds -1. The result array is
1381  * a mapping in "Old to New" mode. 
1382  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1383  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1384  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1385  *          if the node is unused or a new id else. The caller is to delete this
1386  *          array using decrRef() as it is no more needed.  
1387  *  \throw If the coordinates array is not set.
1388  *  \throw If the nodal connectivity of cells is not defined.
1389  *  \throw If the nodal connectivity includes an invalid id.
1390  *
1391  *  \if ENABLE_EXAMPLES
1392  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1393  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1394  *  \endif
1395  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1396  */
1397 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1398 {
1399   nbrOfNodesInUse=-1;
1400   int nbOfNodes(getNumberOfNodes());
1401   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1402   ret->alloc(nbOfNodes,1);
1403   int *traducer=ret->getPointer();
1404   std::fill(traducer,traducer+nbOfNodes,-1);
1405   int nbOfCells=getNumberOfCells();
1406   const int *connIndex=_nodal_connec_index->getConstPointer();
1407   const int *conn=_nodal_connec->getConstPointer();
1408   for(int i=0;i<nbOfCells;i++)
1409     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1410       if(conn[j]>=0)
1411         {
1412           if(conn[j]<nbOfNodes)
1413             traducer[conn[j]]=1;
1414           else
1415             {
1416               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1417               throw INTERP_KERNEL::Exception(oss.str());
1418             }
1419         }
1420   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1421   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1422   return ret.retn();
1423 }
1424
1425 /*!
1426  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1427  * For each cell in \b this the number of nodes constituting cell is computed.
1428  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1429  * So for pohyhedrons some nodes can be counted several times in the returned result.
1430  * 
1431  * \return a newly allocated array
1432  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1433  */
1434 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1435 {
1436   checkConnectivityFullyDefined();
1437   int nbOfCells=getNumberOfCells();
1438   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1439   ret->alloc(nbOfCells,1);
1440   int *retPtr=ret->getPointer();
1441   const int *conn=getNodalConnectivity()->getConstPointer();
1442   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1443   for(int i=0;i<nbOfCells;i++,retPtr++)
1444     {
1445       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1446         *retPtr=connI[i+1]-connI[i]-1;
1447       else
1448         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1449     }
1450   return ret.retn();
1451 }
1452
1453 /*!
1454  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1455  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1456  *
1457  * \return DataArrayInt * - new object to be deallocated by the caller.
1458  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1459  */
1460 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1461 {
1462   checkConnectivityFullyDefined();
1463   int nbOfCells=getNumberOfCells();
1464   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1465   ret->alloc(nbOfCells,1);
1466   int *retPtr=ret->getPointer();
1467   const int *conn=getNodalConnectivity()->getConstPointer();
1468   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1469   for(int i=0;i<nbOfCells;i++,retPtr++)
1470     {
1471       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1472       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1473         *retPtr=(int)s.size();
1474       else
1475         {
1476           s.erase(-1);
1477           *retPtr=(int)s.size();
1478         }
1479     }
1480   return ret.retn();
1481 }
1482
1483 /*!
1484  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1485  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1486  * 
1487  * \return a newly allocated array
1488  */
1489 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1490 {
1491   checkConnectivityFullyDefined();
1492   int nbOfCells=getNumberOfCells();
1493   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1494   ret->alloc(nbOfCells,1);
1495   int *retPtr=ret->getPointer();
1496   const int *conn=getNodalConnectivity()->getConstPointer();
1497   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1498   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1499     {
1500       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1501       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1502     }
1503   return ret.retn();
1504 }
1505
1506 /*!
1507  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1508  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1509  * array mean that the corresponding old node is no more used. 
1510  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1511  *           this->getNumberOfNodes() before call of this method. The caller is to
1512  *           delete this array using decrRef() as it is no more needed. 
1513  *  \throw If the coordinates array is not set.
1514  *  \throw If the nodal connectivity of cells is not defined.
1515  *  \throw If the nodal connectivity includes an invalid id.
1516  *  \sa areAllNodesFetched
1517  *
1518  *  \if ENABLE_EXAMPLES
1519  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1520  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1521  *  \endif
1522  */
1523 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1524 {
1525   return MEDCouplingPointSet::zipCoordsTraducer();
1526 }
1527
1528 /*!
1529  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1530  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1531  */
1532 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1533 {
1534   switch(compType)
1535   {
1536     case 0:
1537       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1538     case 1:
1539       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1540     case 2:
1541       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1542     case 3:
1543       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1544     case 7:
1545       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1546   }
1547   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1548 }
1549
1550 /*!
1551  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1552  */
1553 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1554 {
1555   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1556     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1557   return 0;
1558 }
1559
1560 /*!
1561  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1562  */
1563 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1564 {
1565   int sz=connI[cell1+1]-connI[cell1];
1566   if(sz==connI[cell2+1]-connI[cell2])
1567     {
1568       if(conn[connI[cell1]]==conn[connI[cell2]])
1569         {
1570           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1571           unsigned dim=cm.getDimension();
1572           if(dim!=3)
1573             {
1574               if(dim!=1)
1575                 {
1576                   int sz1=2*(sz-1);
1577                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1578                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1579                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1580                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1581                   return work!=tmp+sz1?1:0;
1582                 }
1583               else
1584                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1585             }
1586           else
1587             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1588         }
1589     }
1590   return 0;
1591 }
1592
1593 /*!
1594  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1595  */
1596 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1597 {
1598   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1599     {
1600       if(conn[connI[cell1]]==conn[connI[cell2]])
1601         {
1602           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1603           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1604           return s1==s2?1:0;
1605         }
1606     }
1607   return 0;
1608 }
1609
1610 /*!
1611  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1612  */
1613 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1614 {
1615   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1616     {
1617       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1618       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1619       return s1==s2?1:0;
1620     }
1621   return 0;
1622 }
1623
1624 /*!
1625  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1626  */
1627 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1628 {
1629   int sz=connI[cell1+1]-connI[cell1];
1630   if(sz==connI[cell2+1]-connI[cell2])
1631     {
1632       if(conn[connI[cell1]]==conn[connI[cell2]])
1633         {
1634           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1635           unsigned dim=cm.getDimension();
1636           if(dim!=3)
1637             {
1638               if(dim!=1)
1639                 {
1640                   int sz1=2*(sz-1);
1641                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1642                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1643                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1644                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1645                   if(work!=tmp+sz1)
1646                     return 1;
1647                   else
1648                     {
1649                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1650                       std::reverse_iterator<int *> it2((int *)tmp);
1651                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1652                         return 2;
1653                       else
1654                         return 0;
1655                     }
1656
1657                   return work!=tmp+sz1?1:0;
1658                 }
1659               else
1660                 {//case of SEG2 and SEG3
1661                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1662                     return 1;
1663                   if(!cm.isQuadratic())
1664                     {
1665                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1666                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1667                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1668                         return 2;
1669                       return 0;
1670                     }
1671                   else
1672                     {
1673                       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])
1674                         return 2;
1675                       return 0;
1676                     }
1677                 }
1678             }
1679           else
1680             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1681         }
1682     }
1683   return 0;
1684 }
1685
1686
1687 /*!
1688  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1689  * by \a compType.
1690  * This method keeps the coordiantes of \a this. This method is time consuming.
1691  *
1692  * \param [in] compType input specifying the technique used to compare cells each other.
1693  *   - 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.
1694  *   - 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)
1695  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1696  *   - 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
1697  * can be used for users not sensitive to orientation of cell
1698  * \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.
1699  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1700  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1701  * \return the correspondance array old to new in a newly allocated array.
1702  * 
1703  */
1704 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1705 {
1706   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1707   getReverseNodalConnectivity(revNodal,revNodalI);
1708   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1709 }
1710
1711 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1712                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1713 {
1714   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1715   int nbOfCells=nodalI->getNumberOfTuples()-1;
1716   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1717   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1718   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1719   std::vector<bool> isFetched(nbOfCells,false);
1720   if(startCellId==0)
1721     {
1722       for(int i=0;i<nbOfCells;i++)
1723         {
1724           if(!isFetched[i])
1725             {
1726               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1727               std::vector<int> v,v2;
1728               if(connOfNode!=connPtr+connIPtr[i+1])
1729                 {
1730                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1731                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1732                   connOfNode++;
1733                 }
1734               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1735                 if(*connOfNode>=0)
1736                   {
1737                     v=v2;
1738                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1739                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1740                     v2.resize(std::distance(v2.begin(),it));
1741                   }
1742               if(v2.size()>1)
1743                 {
1744                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1745                     {
1746                       int pos=commonCellsI->back();
1747                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1748                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1749                         isFetched[*it]=true;
1750                     }
1751                 }
1752             }
1753         }
1754     }
1755   else
1756     {
1757       for(int i=startCellId;i<nbOfCells;i++)
1758         {
1759           if(!isFetched[i])
1760             {
1761               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1762               std::vector<int> v,v2;
1763               if(connOfNode!=connPtr+connIPtr[i+1])
1764                 {
1765                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1766                   connOfNode++;
1767                 }
1768               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1769                 if(*connOfNode>=0)
1770                   {
1771                     v=v2;
1772                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1773                     v2.resize(std::distance(v2.begin(),it));
1774                   }
1775               if(v2.size()>1)
1776                 {
1777                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1778                     {
1779                       int pos=commonCellsI->back();
1780                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1781                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1782                         isFetched[*it]=true;
1783                     }
1784                 }
1785             }
1786         }
1787     }
1788   commonCellsArr=commonCells.retn();
1789   commonCellsIArr=commonCellsI.retn();
1790 }
1791
1792 /*!
1793  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1794  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1795  * than \a this->getNumberOfCells() in the returned array means that there is no
1796  * corresponding cell in \a this mesh.
1797  * It is expected that \a this and \a other meshes share the same node coordinates
1798  * array, if it is not so an exception is thrown. 
1799  *  \param [in] other - the mesh to compare with.
1800  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1801  *         valid values [0,1,2], see zipConnectivityTraducer().
1802  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1803  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1804  *         values. The caller is to delete this array using
1805  *         decrRef() as it is no more needed.
1806  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1807  *         mesh.
1808  *
1809  *  \if ENABLE_EXAMPLES
1810  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1811  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1812  *  \endif
1813  *  \sa checkDeepEquivalOnSameNodesWith()
1814  *  \sa checkGeoEquivalWith()
1815  */
1816 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1817 {
1818   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1819   int nbOfCells=getNumberOfCells();
1820   static const int possibleCompType[]={0,1,2};
1821   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1822     {
1823       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1824       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1825       oss << " !";
1826       throw INTERP_KERNEL::Exception(oss.str());
1827     }
1828   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1829   arr=o2n->subArray(nbOfCells);
1830   arr->setName(other->getName());
1831   int tmp;
1832   if(other->getNumberOfCells()==0)
1833     return true;
1834   return arr->getMaxValue(tmp)<nbOfCells;
1835 }
1836
1837 /*!
1838  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1839  * This method tries to determine if \b other is fully included in \b this.
1840  * The main difference is that this method is not expected to throw exception.
1841  * This method has two outputs :
1842  *
1843  * \param other other mesh
1844  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1845  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1846  */
1847 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1848 {
1849   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1850   DataArrayInt *commonCells=0,*commonCellsI=0;
1851   int thisNbCells=getNumberOfCells();
1852   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1853   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1854   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1855   int otherNbCells=other->getNumberOfCells();
1856   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1857   arr2->alloc(otherNbCells,1);
1858   arr2->fillWithZero();
1859   int *arr2Ptr=arr2->getPointer();
1860   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1861   for(int i=0;i<nbOfCommon;i++)
1862     {
1863       int start=commonCellsPtr[commonCellsIPtr[i]];
1864       if(start<thisNbCells)
1865         {
1866           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1867             {
1868               int sig=commonCellsPtr[j]>0?1:-1;
1869               int val=std::abs(commonCellsPtr[j])-1;
1870               if(val>=thisNbCells)
1871                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1872             }
1873         }
1874     }
1875   arr2->setName(other->getName());
1876   if(arr2->presenceOfValue(0))
1877     return false;
1878   arr=arr2.retn();
1879   return true;
1880 }
1881
1882 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1883 {
1884   if(!other)
1885     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1886   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1887   if(!otherC)
1888     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1889   std::vector<const MEDCouplingUMesh *> ms(2);
1890   ms[0]=this;
1891   ms[1]=otherC;
1892   return MergeUMeshesOnSameCoords(ms);
1893 }
1894
1895 /*!
1896  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1897  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1898  * cellIds is not given explicitely but by a range python like.
1899  * 
1900  * \param start
1901  * \param end
1902  * \param step
1903  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see MEDCoupling::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1904  * \return a newly allocated
1905  * 
1906  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1907  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1908  */
1909 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
1910 {
1911   if(getMeshDimension()!=-1)
1912     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
1913   else
1914     {
1915       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
1916       if(newNbOfCells!=1)
1917         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1918       if(start!=0)
1919         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1920       incrRef();
1921       return const_cast<MEDCouplingUMesh *>(this);
1922     }
1923 }
1924
1925 /*!
1926  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1927  * The result mesh shares or not the node coordinates array with \a this mesh depending
1928  * on \a keepCoords parameter.
1929  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1930  *           to write this mesh to the MED file, its cells must be sorted using
1931  *           sortCellsInMEDFileFrmt().
1932  *  \param [in] begin - an array of cell ids to include to the new mesh.
1933  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1934  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1935  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1936  *         by calling zipCoords().
1937  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
1938  *         to delete this mesh using decrRef() as it is no more needed. 
1939  *  \throw If the coordinates array is not set.
1940  *  \throw If the nodal connectivity of cells is not defined.
1941  *  \throw If any cell id in the array \a begin is not valid.
1942  *
1943  *  \if ENABLE_EXAMPLES
1944  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1945  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1946  *  \endif
1947  */
1948 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1949 {
1950   if(getMeshDimension()!=-1)
1951     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
1952   else
1953     {
1954       if(end-begin!=1)
1955         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1956       if(begin[0]!=0)
1957         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1958       incrRef();
1959       return const_cast<MEDCouplingUMesh *>(this);
1960     }
1961 }
1962
1963 /*!
1964  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1965  *
1966  * 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.
1967  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1968  * The number of cells of \b this will remain the same with this method.
1969  *
1970  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
1971  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
1972  * \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 ).
1973  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1974  */
1975 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1976 {
1977   checkConnectivityFullyDefined();
1978   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1979   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1980     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1981   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1982     {
1983       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1984       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1985       throw INTERP_KERNEL::Exception(oss.str());
1986     }
1987   std::size_t nbOfCellsToModify(std::distance(cellIdsBg,cellIdsEnd));
1988   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1989     {
1990       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1991       throw INTERP_KERNEL::Exception(oss.str());
1992     }
1993   std::size_t nbOfCells(getNumberOfCells());
1994   bool easyAssign(true);
1995   const int *connI(_nodal_connec_index->begin());
1996   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->begin();
1997   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1998     {
1999       if(*it>=0 && *it<(int)nbOfCells)
2000         {
2001           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2002         }
2003       else
2004         {
2005           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2006           throw INTERP_KERNEL::Exception(oss.str());
2007         }
2008     }
2009   if(easyAssign)
2010     {
2011       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2012       computeTypes();
2013     }
2014   else
2015     {
2016       DataArrayInt *arrOut=0,*arrIOut=0;
2017       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2018                                                arrOut,arrIOut);
2019       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2020       setConnectivity(arrOut,arrIOut,true);
2021     }
2022 }
2023
2024 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2025 {
2026   checkConnectivityFullyDefined();
2027   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2028   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2029     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2030   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2031     {
2032       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2033       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2034       throw INTERP_KERNEL::Exception(oss.str());
2035     }
2036   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2037   if(nbOfCellsToModify!=(int)otherOnSameCoordsThanThis.getNumberOfCells())
2038     {
2039       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2040       throw INTERP_KERNEL::Exception(oss.str());
2041     }
2042   int nbOfCells=getNumberOfCells();
2043   bool easyAssign=true;
2044   const int *connI=_nodal_connec_index->getConstPointer();
2045   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2046   int it=start;
2047   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2048     {
2049       if(it>=0 && it<nbOfCells)
2050         {
2051           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2052         }
2053       else
2054         {
2055           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2056           throw INTERP_KERNEL::Exception(oss.str());
2057         }
2058     }
2059   if(easyAssign)
2060     {
2061       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2062       computeTypes();
2063     }
2064   else
2065     {
2066       DataArrayInt *arrOut=0,*arrIOut=0;
2067       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2068                                                 arrOut,arrIOut);
2069       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2070       setConnectivity(arrOut,arrIOut,true);
2071     }
2072 }                      
2073
2074
2075 /*!
2076  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2077  * this->getMeshDimension(), that bound some cells of \a this mesh.
2078  * The cells of lower dimension to include to the result mesh are selected basing on
2079  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2080  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2081  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2082  * created mesh shares the node coordinates array with \a this mesh. 
2083  *  \param [in] begin - the array of node ids.
2084  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2085  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2086  *         array \a begin are added, else cells whose any node is in the
2087  *         array \a begin are added.
2088  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2089  *         to delete this mesh using decrRef() as it is no more needed. 
2090  *  \throw If the coordinates array is not set.
2091  *  \throw If the nodal connectivity of cells is not defined.
2092  *  \throw If any node id in \a begin is not valid.
2093  *
2094  *  \if ENABLE_EXAMPLES
2095  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2096  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2097  *  \endif
2098  */
2099 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2100 {
2101   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2102   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2103   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2104   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2105   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2106 }
2107
2108 /*!
2109  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2110  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2111  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2112  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2113  *         by calling zipCoords().
2114  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2115  *         to delete this mesh using decrRef() as it is no more needed. 
2116  *  \throw If the coordinates array is not set.
2117  *  \throw If the nodal connectivity of cells is not defined.
2118  *
2119  *  \if ENABLE_EXAMPLES
2120  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2121  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2122  *  \endif
2123  */
2124 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2125 {
2126   DataArrayInt *desc=DataArrayInt::New();
2127   DataArrayInt *descIndx=DataArrayInt::New();
2128   DataArrayInt *revDesc=DataArrayInt::New();
2129   DataArrayInt *revDescIndx=DataArrayInt::New();
2130   //
2131   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2132   revDesc->decrRef();
2133   desc->decrRef();
2134   descIndx->decrRef();
2135   int nbOfCells=meshDM1->getNumberOfCells();
2136   const int *revDescIndxC=revDescIndx->getConstPointer();
2137   std::vector<int> boundaryCells;
2138   for(int i=0;i<nbOfCells;i++)
2139     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2140       boundaryCells.push_back(i);
2141   revDescIndx->decrRef();
2142   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2143   return ret;
2144 }
2145
2146 /*!
2147  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2148  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2149  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2150  */
2151 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2152 {
2153   checkFullyDefined();
2154   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2155   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2156   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2157   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2158   //
2159   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2160   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2161   //
2162   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2163   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2164   const int *revDescPtr=revDesc->getConstPointer();
2165   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2166   int nbOfCells=getNumberOfCells();
2167   std::vector<bool> ret1(nbOfCells,false);
2168   int sz=0;
2169   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2170     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2171       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2172   //
2173   DataArrayInt *ret2=DataArrayInt::New();
2174   ret2->alloc(sz,1);
2175   int *ret2Ptr=ret2->getPointer();
2176   sz=0;
2177   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2178     if(*it)
2179       *ret2Ptr++=sz;
2180   ret2->setName("BoundaryCells");
2181   return ret2;
2182 }
2183
2184 /*!
2185  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2186  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2187  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2188  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2189  *
2190  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2191  * This method also returns the cells ids set s1 which contains the cell ids in \b this for which one of the dim-1 constituent
2192  * equals a cell in \b otherDimM1OnSameCoords.
2193  *
2194  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2195  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2196  *
2197  * \param [in] otherDimM1OnSameCoords
2198  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2199  * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1 \b indexed into the \b cellIdsRk0 subset. To get the absolute ids of s1, simply invoke
2200  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2201  */
2202 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2203 {
2204   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2205     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2206   checkConnectivityFullyDefined();
2207   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2208   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2209     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2210   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2211   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2212   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2213   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2214   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2215   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2216   DataArrayInt *idsOtherInConsti=0;
2217   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2218   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2219   if(!b)
2220     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2221   std::set<int> s1;
2222   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2223     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2224   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2225   s1arr_renum1->sort();
2226   cellIdsRk0=s0arr.retn();
2227   //cellIdsRk1=s_renum1.retn();
2228   cellIdsRk1=s1arr_renum1.retn();
2229 }
2230
2231 /*!
2232  * 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
2233  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2234  * 
2235  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2236  */
2237 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2238 {
2239   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2240   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2241   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2242   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2243   //
2244   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2245   revDesc=0; desc=0; descIndx=0;
2246   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2247   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2248   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2249 }
2250
2251 /*!
2252  * Finds nodes lying on the boundary of \a this mesh.
2253  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2254  *          nodes. The caller is to delete this array using decrRef() as it is no
2255  *          more needed.
2256  *  \throw If the coordinates array is not set.
2257  *  \throw If the nodal connectivity of cells is node defined.
2258  *
2259  *  \if ENABLE_EXAMPLES
2260  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2261  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2262  *  \endif
2263  */
2264 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2265 {
2266   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2267   return skin->computeFetchedNodeIds();
2268 }
2269
2270 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2271 {
2272   incrRef();
2273   return const_cast<MEDCouplingUMesh *>(this);
2274 }
2275
2276 /*!
2277  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2278  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2279  * 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.
2280  * 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.
2281  * 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.
2282  *
2283  * \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
2284  *             parameter is altered during the call.
2285  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2286  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2287  * \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.
2288  *
2289  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2290  */
2291 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2292                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2293 {
2294   typedef MCAuto<DataArrayInt> DAInt;
2295   typedef MCAuto<MEDCouplingUMesh> MCUMesh;
2296
2297   checkFullyDefined();
2298   otherDimM1OnSameCoords.checkFullyDefined();
2299   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2300     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2301   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2302     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2303
2304   // Checking star-shaped M1 group:
2305   DAInt dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2306   MCUMesh meshM2 = otherDimM1OnSameCoords.buildDescendingConnectivity(dt0, dit0, rdt0, rdit0);
2307   DAInt dsi = rdit0->deltaShiftIndex();
2308   DAInt idsTmp0 = dsi->findIdsNotInRange(-1, 3);
2309   if(idsTmp0->getNumberOfTuples())
2310     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group: group is too complex: some points (or edges) have more than two connected segments (or faces)!");
2311   dt0=0; dit0=0; rdt0=0; rdit0=0; idsTmp0=0;
2312
2313   // Get extreme nodes from the group (they won't be duplicated), ie nodes belonging to boundary cells of M1
2314   DAInt xtremIdsM2 = dsi->findIdsEqual(1); dsi = 0;
2315   MCUMesh meshM2Part = static_cast<MEDCouplingUMesh *>(meshM2->buildPartOfMySelf(xtremIdsM2->begin(), xtremIdsM2->end(),true));
2316   DAInt xtrem = meshM2Part->computeFetchedNodeIds();
2317   // Remove from the list points on the boundary of the M0 mesh (those need duplication!)
2318   dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2319   MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;
2320   dsi = rdit0->deltaShiftIndex();
2321   DAInt boundSegs = dsi->findIdsEqual(1);   // boundary segs/faces of the M0 mesh
2322   MCUMesh m0descSkin = static_cast<MEDCouplingUMesh *>(m0desc->buildPartOfMySelf(boundSegs->begin(),boundSegs->end(), true));
2323   DAInt fNodes = m0descSkin->computeFetchedNodeIds();
2324   // In 3D, some points on the boundary of M0 still need duplication:
2325   DAInt notDup = 0;
2326   if (getMeshDimension() == 3)
2327     {
2328       DAInt dnu1=DataArrayInt::New(), dnu2=DataArrayInt::New(), dnu3=DataArrayInt::New(), dnu4=DataArrayInt::New();
2329       MCUMesh m0descSkinDesc = m0descSkin->buildDescendingConnectivity(dnu1, dnu2, dnu3, dnu4);
2330       dnu1=0;dnu2=0;dnu3=0;dnu4=0;
2331       DataArrayInt * corresp=0;
2332       meshM2->areCellsIncludedIn(m0descSkinDesc,2,corresp);
2333       DAInt validIds = corresp->findIdsInRange(0, meshM2->getNumberOfCells());
2334       corresp->decrRef();
2335       if (validIds->getNumberOfTuples())
2336         {
2337           MCUMesh m1IntersecSkin = static_cast<MEDCouplingUMesh *>(m0descSkinDesc->buildPartOfMySelf(validIds->begin(), validIds->end(), true));
2338           DAInt notDuplSkin = m1IntersecSkin->findBoundaryNodes();
2339           DAInt fNodes1 = fNodes->buildSubstraction(notDuplSkin);
2340           notDup = xtrem->buildSubstraction(fNodes1);
2341         }
2342       else
2343         notDup = xtrem->buildSubstraction(fNodes);
2344     }
2345   else
2346     notDup = xtrem->buildSubstraction(fNodes);
2347
2348   // Now compute cells around group (i.e. cells where we will do the propagation to identify the two sub-sets delimited by the group)
2349   DAInt m1Nodes = otherDimM1OnSameCoords.computeFetchedNodeIds();
2350   DAInt dupl = m1Nodes->buildSubstraction(notDup);
2351   DAInt cellsAroundGroup = getCellIdsLyingOnNodes(dupl->begin(), dupl->end(), false);  // false= take cell in, even if not all nodes are in notDup
2352
2353   //
2354   MCUMesh m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true));
2355   int nCells2 = m0Part2->getNumberOfCells();
2356   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2357   MCUMesh m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2358
2359   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2360   DataArrayInt *tmp00=0,*tmp11=0;
2361   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2362   DAInt neighInit00(tmp00);
2363   DAInt neighIInit00(tmp11);
2364   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2365   DataArrayInt *idsTmp=0;
2366   m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2367   DAInt ids(idsTmp);
2368   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2369   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2370   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2371   DataArrayInt *tmp0=0,*tmp1=0;
2372   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2373   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2374   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2375   DAInt neigh00(tmp0);
2376   DAInt neighI00(tmp1);
2377
2378   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2379   int seed = 0, nIter = 0;
2380   int nIterMax = nCells2+1; // Safety net for the loop
2381   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2382   hitCells->fillWithValue(-1);
2383   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2384   cellsToModifyConn0_torenum->alloc(0,1);
2385   while (nIter < nIterMax)
2386     {
2387       DAInt t = hitCells->findIdsEqual(-1);
2388       if (!t->getNumberOfTuples())
2389         break;
2390       // Connex zone without the crack (to compute the next seed really)
2391       int dnu;
2392       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2393       std::size_t cnt(0);
2394       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2395         hitCells->setIJ(*ptr,0,1);
2396       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2397       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2398       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2399       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2400       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2401       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2402       DAInt intersec = nonHitCells->buildIntersection(comple);
2403       if (intersec->getNumberOfTuples())
2404         { seed = intersec->getIJ(0,0); }
2405       else
2406         { break; }
2407       nIter++;
2408     }
2409   if (nIter >= nIterMax)
2410     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2411
2412   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2413   cellsToModifyConn0_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2414   cellsToModifyConn1_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2415   //
2416   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2417   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2418   nodeIdsToDuplicate=dupl.retn();
2419 }
2420
2421 /*!
2422  * This method operates a modification of the connectivity and coords in \b this.
2423  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2424  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2425  * 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
2426  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2427  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2428  * 
2429  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2430  * 
2431  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2432  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2433  */
2434 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2435 {
2436   int nbOfNodes=getNumberOfNodes();
2437   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2438   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2439 }
2440
2441 /*!
2442  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2443  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2444  *
2445  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2446  *
2447  * \sa renumberNodesInConn
2448  */
2449 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2450 {
2451   checkConnectivityFullyDefined();
2452   int *conn(getNodalConnectivity()->getPointer());
2453   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2454   int nbOfCells(getNumberOfCells());
2455   for(int i=0;i<nbOfCells;i++)
2456     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2457       {
2458         int& node=conn[iconn];
2459         if(node>=0)//avoid polyhedron separator
2460           {
2461             node+=offset;
2462           }
2463       }
2464   _nodal_connec->declareAsNew();
2465   updateTime();
2466 }
2467
2468 /*!
2469  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2470  *  of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2471  *  of a big mesh.
2472  */
2473 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2474 {
2475   checkConnectivityFullyDefined();
2476   int *conn(getNodalConnectivity()->getPointer());
2477   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2478   int nbOfCells(getNumberOfCells());
2479   for(int i=0;i<nbOfCells;i++)
2480     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2481       {
2482         int& node=conn[iconn];
2483         if(node>=0)//avoid polyhedron separator
2484           {
2485             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2486             if(it!=newNodeNumbersO2N.end())
2487               {
2488                 node=(*it).second;
2489               }
2490             else
2491               {
2492                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2493                 throw INTERP_KERNEL::Exception(oss.str());
2494               }
2495           }
2496       }
2497   _nodal_connec->declareAsNew();
2498   updateTime();
2499 }
2500
2501 /*!
2502  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2503  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2504  * This method is a generalization of shiftNodeNumbersInConn().
2505  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2506  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2507  *         this->getNumberOfNodes(), in "Old to New" mode. 
2508  *         See \ref numbering for more info on renumbering modes.
2509  *  \throw If the nodal connectivity of cells is not defined.
2510  *
2511  *  \if ENABLE_EXAMPLES
2512  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2513  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2514  *  \endif
2515  */
2516 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2517 {
2518   checkConnectivityFullyDefined();
2519   int *conn=getNodalConnectivity()->getPointer();
2520   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2521   int nbOfCells(getNumberOfCells());
2522   for(int i=0;i<nbOfCells;i++)
2523     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2524       {
2525         int& node=conn[iconn];
2526         if(node>=0)//avoid polyhedron separator
2527           {
2528             node=newNodeNumbersO2N[node];
2529           }
2530       }
2531   _nodal_connec->declareAsNew();
2532   updateTime();
2533 }
2534
2535 /*!
2536  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2537  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2538  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2539  * 
2540  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2541  */
2542 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2543 {
2544   checkConnectivityFullyDefined();
2545   int *conn=getNodalConnectivity()->getPointer();
2546   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2547   int nbOfCells=getNumberOfCells();
2548   for(int i=0;i<nbOfCells;i++)
2549     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2550       {
2551         int& node=conn[iconn];
2552         if(node>=0)//avoid polyhedron separator
2553           {
2554             node+=delta;
2555           }
2556       }
2557   _nodal_connec->declareAsNew();
2558   updateTime();
2559 }
2560
2561 /*!
2562  * This method operates a modification of the connectivity in \b this.
2563  * 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.
2564  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2565  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2566  * 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
2567  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2568  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2569  * 
2570  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2571  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2572  * 
2573  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2574  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2575  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2576  */
2577 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2578 {
2579   checkConnectivityFullyDefined();
2580   std::map<int,int> m;
2581   int val=offset;
2582   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2583     m[*work]=val;
2584   int *conn=getNodalConnectivity()->getPointer();
2585   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2586   int nbOfCells=getNumberOfCells();
2587   for(int i=0;i<nbOfCells;i++)
2588     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2589       {
2590         int& node=conn[iconn];
2591         if(node>=0)//avoid polyhedron separator
2592           {
2593             std::map<int,int>::iterator it=m.find(node);
2594             if(it!=m.end())
2595               node=(*it).second;
2596           }
2597       }
2598   updateTime();
2599 }
2600
2601 /*!
2602  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2603  *
2604  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2605  * After the call of this method the number of cells remains the same as before.
2606  *
2607  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2608  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2609  * be strictly in [0;this->getNumberOfCells()).
2610  *
2611  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2612  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2613  * should be contained in[0;this->getNumberOfCells()).
2614  * 
2615  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2616  * \param check
2617  */
2618 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2619 {
2620   checkConnectivityFullyDefined();
2621   int nbCells=getNumberOfCells();
2622   const int *array=old2NewBg;
2623   if(check)
2624     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2625   //
2626   const int *conn=_nodal_connec->getConstPointer();
2627   const int *connI=_nodal_connec_index->getConstPointer();
2628   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2629   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2630   const int *n2oPtr=n2o->begin();
2631   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2632   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2633   newConn->copyStringInfoFrom(*_nodal_connec);
2634   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2635   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2636   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2637   //
2638   int *newC=newConn->getPointer();
2639   int *newCI=newConnI->getPointer();
2640   int loc=0;
2641   newCI[0]=loc;
2642   for(int i=0;i<nbCells;i++)
2643     {
2644       int pos=n2oPtr[i];
2645       int nbOfElts=connI[pos+1]-connI[pos];
2646       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2647       loc+=nbOfElts;
2648       newCI[i+1]=loc;
2649     }
2650   //
2651   setConnectivity(newConn,newConnI);
2652   if(check)
2653     free(const_cast<int *>(array));
2654 }
2655
2656 /*!
2657  * Finds cells whose bounding boxes intersect a given bounding box.
2658  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2659  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2660  *         zMax (if in 3D). 
2661  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2662  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2663  *         extent of the bounding box of cell to produce an addition to this bounding box.
2664  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2665  *         cells. The caller is to delete this array using decrRef() as it is no more
2666  *         needed. 
2667  *  \throw If the coordinates array is not set.
2668  *  \throw If the nodal connectivity of cells is not defined.
2669  *
2670  *  \if ENABLE_EXAMPLES
2671  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2672  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2673  *  \endif
2674  */
2675 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2676 {
2677   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2678   if(getMeshDimension()==-1)
2679     {
2680       elems->pushBackSilent(0);
2681       return elems.retn();
2682     }
2683   int dim=getSpaceDimension();
2684   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2685   const int* conn      = getNodalConnectivity()->getConstPointer();
2686   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2687   const double* coords = getCoords()->getConstPointer();
2688   int nbOfCells=getNumberOfCells();
2689   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2690     {
2691       for (int i=0; i<dim; i++)
2692         {
2693           elem_bb[i*2]=std::numeric_limits<double>::max();
2694           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2695         }
2696
2697       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2698         {
2699           int node= conn[inode];
2700           if(node>=0)//avoid polyhedron separator
2701             {
2702               for (int idim=0; idim<dim; idim++)
2703                 {
2704                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2705                     {
2706                       elem_bb[idim*2] = coords[node*dim+idim] ;
2707                     }
2708                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2709                     {
2710                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2711                     }
2712                 }
2713             }
2714         }
2715       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2716         elems->pushBackSilent(ielem);
2717     }
2718   return elems.retn();
2719 }
2720
2721 /*!
2722  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2723  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2724  * added in 'elems' parameter.
2725  */
2726 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2727 {
2728   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2729   if(getMeshDimension()==-1)
2730     {
2731       elems->pushBackSilent(0);
2732       return elems.retn();
2733     }
2734   int dim=getSpaceDimension();
2735   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2736   const int* conn      = getNodalConnectivity()->getConstPointer();
2737   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2738   const double* coords = getCoords()->getConstPointer();
2739   int nbOfCells=getNumberOfCells();
2740   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2741     {
2742       for (int i=0; i<dim; i++)
2743         {
2744           elem_bb[i*2]=std::numeric_limits<double>::max();
2745           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2746         }
2747
2748       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2749         {
2750           int node= conn[inode];
2751           if(node>=0)//avoid polyhedron separator
2752             {
2753               for (int idim=0; idim<dim; idim++)
2754                 {
2755                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2756                     {
2757                       elem_bb[idim*2] = coords[node*dim+idim] ;
2758                     }
2759                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2760                     {
2761                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2762                     }
2763                 }
2764             }
2765         }
2766       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2767         elems->pushBackSilent(ielem);
2768     }
2769   return elems.retn();
2770 }
2771
2772 /*!
2773  * Returns a type of a cell by its id.
2774  *  \param [in] cellId - the id of the cell of interest.
2775  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2776  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2777  */
2778 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(std::size_t cellId) const
2779 {
2780   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2781   if(cellId<_nodal_connec_index->getNbOfElems()-1)
2782     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2783   else
2784     {
2785       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2786       throw INTERP_KERNEL::Exception(oss.str());
2787     }
2788 }
2789
2790 /*!
2791  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2792  * This method does not throw exception if geometric type \a type is not in \a this.
2793  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2794  * The coordinates array is not considered here.
2795  *
2796  * \param [in] type the geometric type
2797  * \return cell ids in this having geometric type \a type.
2798  */
2799 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2800 {
2801
2802   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2803   ret->alloc(0,1);
2804   checkConnectivityFullyDefined();
2805   int nbCells=getNumberOfCells();
2806   int mdim=getMeshDimension();
2807   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2808   if(mdim!=(int)cm.getDimension())
2809     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2810   const int *ptI=_nodal_connec_index->getConstPointer();
2811   const int *pt=_nodal_connec->getConstPointer();
2812   for(int i=0;i<nbCells;i++)
2813     {
2814       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2815         ret->pushBackSilent(i);
2816     }
2817   return ret.retn();
2818 }
2819
2820 /*!
2821  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2822  */
2823 std::size_t MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2824 {
2825   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2826   std::size_t nbOfCells(getNumberOfCells()),ret(0);
2827   for(std::size_t i=0;i<nbOfCells;i++)
2828     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2829       ret++;
2830   return ret;
2831 }
2832
2833 /*!
2834  * Returns the nodal connectivity of a given cell.
2835  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2836  * all returned node ids can be used in getCoordinatesOfNode().
2837  *  \param [in] cellId - an id of the cell of interest.
2838  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2839  *         cleared before the appending.
2840  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2841  */
2842 void MEDCouplingUMesh::getNodeIdsOfCell(std::size_t cellId, std::vector<int>& conn) const
2843 {
2844   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2845   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2846     if(*w>=0)
2847       conn.push_back(*w);
2848 }
2849
2850 std::string MEDCouplingUMesh::simpleRepr() const
2851 {
2852   static const char msg0[]="No coordinates specified !";
2853   std::ostringstream ret;
2854   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2855   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2856   int tmpp1,tmpp2;
2857   double tt=getTime(tmpp1,tmpp2);
2858   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2859   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2860   if(_mesh_dim>=-1)
2861     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2862   else
2863     { ret << " Mesh dimension has not been set or is invalid !"; }
2864   if(_coords!=0)
2865     {
2866       const int spaceDim=getSpaceDimension();
2867       ret << spaceDim << "\nInfo attached on space dimension : ";
2868       for(int i=0;i<spaceDim;i++)
2869         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2870       ret << "\n";
2871     }
2872   else
2873     ret << msg0 << "\n";
2874   ret << "Number of nodes : ";
2875   if(_coords!=0)
2876     ret << getNumberOfNodes() << "\n";
2877   else
2878     ret << msg0 << "\n";
2879   ret << "Number of cells : ";
2880   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2881     ret << getNumberOfCells() << "\n";
2882   else
2883     ret << "No connectivity specified !" << "\n";
2884   ret << "Cell types present : ";
2885   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2886     {
2887       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2888       ret << cm.getRepr() << " ";
2889     }
2890   ret << "\n";
2891   return ret.str();
2892 }
2893
2894 std::string MEDCouplingUMesh::advancedRepr() const
2895 {
2896   std::ostringstream ret;
2897   ret << simpleRepr();
2898   ret << "\nCoordinates array : \n___________________\n\n";
2899   if(_coords)
2900     _coords->reprWithoutNameStream(ret);
2901   else
2902     ret << "No array set !\n";
2903   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2904   reprConnectivityOfThisLL(ret);
2905   return ret.str();
2906 }
2907
2908 /*!
2909  * This method returns a C++ code that is a dump of \a this.
2910  * This method will throw if this is not fully defined.
2911  */
2912 std::string MEDCouplingUMesh::cppRepr() const
2913 {
2914   static const char coordsName[]="coords";
2915   static const char connName[]="conn";
2916   static const char connIName[]="connI";
2917   checkFullyDefined();
2918   std::ostringstream ret; ret << "// coordinates" << std::endl;
2919   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2920   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2921   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2922   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2923   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2924   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2925   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2926   return ret.str();
2927 }
2928
2929 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2930 {
2931   std::ostringstream ret;
2932   reprConnectivityOfThisLL(ret);
2933   return ret.str();
2934 }
2935
2936 /*!
2937  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2938  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2939  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2940  * some algos).
2941  * 
2942  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2943  * 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
2944  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2945  */
2946 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2947 {
2948   int mdim=getMeshDimension();
2949   if(mdim<0)
2950     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2951   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2952   MCAuto<DataArrayInt> tmp1,tmp2;
2953   bool needToCpyCT=true;
2954   if(!_nodal_connec)
2955     {
2956       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2957       needToCpyCT=false;
2958     }
2959   else
2960     {
2961       tmp1=_nodal_connec;
2962       tmp1->incrRef();
2963     }
2964   if(!_nodal_connec_index)
2965     {
2966       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2967       needToCpyCT=false;
2968     }
2969   else
2970     {
2971       tmp2=_nodal_connec_index;
2972       tmp2->incrRef();
2973     }
2974   ret->setConnectivity(tmp1,tmp2,false);
2975   if(needToCpyCT)
2976     ret->_types=_types;
2977   if(!_coords)
2978     {
2979       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2980       ret->setCoords(coords);
2981     }
2982   else
2983     ret->setCoords(_coords);
2984   return ret.retn();
2985 }
2986
2987 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2988 {
2989   const int *ptI=_nodal_connec_index->getConstPointer();
2990   const int *pt=_nodal_connec->getConstPointer();
2991   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2992     return ptI[cellId+1]-ptI[cellId]-1;
2993   else
2994     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2995 }
2996
2997 /*!
2998  * Returns types of cells of the specified part of \a this mesh.
2999  * This method avoids computing sub-mesh explicitely to get its types.
3000  *  \param [in] begin - an array of cell ids of interest.
3001  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3002  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3003  *         describing the cell types. 
3004  *  \throw If the coordinates array is not set.
3005  *  \throw If the nodal connectivity of cells is not defined.
3006  *  \sa getAllGeoTypes()
3007  */
3008 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3009 {
3010   checkFullyDefined();
3011   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3012   const int *conn=_nodal_connec->getConstPointer();
3013   const int *connIndex=_nodal_connec_index->getConstPointer();
3014   for(const int *w=begin;w!=end;w++)
3015     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3016   return ret;
3017 }
3018
3019 /*!
3020  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3021  * Optionally updates
3022  * a set of types of cells constituting \a this mesh. 
3023  * This method is for advanced users having prepared their connectivity before. For
3024  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3025  *  \param [in] conn - the nodal connectivity array. 
3026  *  \param [in] connIndex - the nodal connectivity index array.
3027  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3028  *         mesh is updated.
3029  */
3030 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3031 {
3032   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3033   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3034   if(isComputingTypes)
3035     computeTypes();
3036   declareAsNew();
3037 }
3038
3039 /*!
3040  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3041  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3042  */
3043 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCpy):MEDCouplingPointSet(other,deepCpy),_mesh_dim(other._mesh_dim),
3044     _nodal_connec(0),_nodal_connec_index(0),
3045     _types(other._types)
3046 {
3047   if(other._nodal_connec)
3048     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCpy);
3049   if(other._nodal_connec_index)
3050     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCpy);
3051 }
3052
3053 MEDCouplingUMesh::~MEDCouplingUMesh()
3054 {
3055   if(_nodal_connec)
3056     _nodal_connec->decrRef();
3057   if(_nodal_connec_index)
3058     _nodal_connec_index->decrRef();
3059 }
3060
3061 /*!
3062  * Recomputes a set of cell types of \a this mesh. For more info see
3063  * \ref MEDCouplingUMeshNodalConnectivity.
3064  */
3065 void MEDCouplingUMesh::computeTypes()
3066 {
3067   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3068 }
3069
3070
3071 /*!
3072  * Returns a number of cells constituting \a this mesh. 
3073  *  \return int - the number of cells in \a this mesh.
3074  *  \throw If the nodal connectivity of cells is not defined.
3075  */
3076 std::size_t MEDCouplingUMesh::getNumberOfCells() const
3077
3078   if(_nodal_connec_index)
3079     return _nodal_connec_index->getNumberOfTuples()-1;
3080   else
3081     if(_mesh_dim==-1)
3082       return 1;
3083     else
3084       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3085 }
3086
3087 /*!
3088  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3089  * mesh. For more info see \ref meshes.
3090  *  \return int - the dimension of \a this mesh.
3091  *  \throw If the mesh dimension is not defined using setMeshDimension().
3092  */
3093 int MEDCouplingUMesh::getMeshDimension() const
3094 {
3095   if(_mesh_dim<-1)
3096     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3097   return _mesh_dim;
3098 }
3099
3100 /*!
3101  * Returns a length of the nodal connectivity array.
3102  * This method is for test reason. Normally the integer returned is not useable by
3103  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3104  *  \return int - the length of the nodal connectivity array.
3105  */
3106 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3107 {
3108   return _nodal_connec->getNbOfElems();
3109 }
3110
3111 /*!
3112  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3113  */
3114 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3115 {
3116   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3117   tinyInfo.push_back(getMeshDimension());
3118   tinyInfo.push_back(getNumberOfCells());
3119   if(_nodal_connec)
3120     tinyInfo.push_back(getNodalConnectivityArrayLen());
3121   else
3122     tinyInfo.push_back(-1);
3123 }
3124
3125 /*!
3126  * First step of unserialization process.
3127  */
3128 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3129 {
3130   return tinyInfo[6]<=0;
3131 }
3132
3133 /*!
3134  * Second step of serialization process.
3135  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3136  * \param a1
3137  * \param a2
3138  * \param littleStrings
3139  */
3140 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3141 {
3142   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3143   if(tinyInfo[5]!=-1)
3144     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3145 }
3146
3147 /*!
3148  * Third and final step of serialization process.
3149  */
3150 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3151 {
3152   MEDCouplingPointSet::serialize(a1,a2);
3153   if(getMeshDimension()>-1)
3154     {
3155       a1=DataArrayInt::New();
3156       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3157       int *ptA1=a1->getPointer();
3158       const int *conn=getNodalConnectivity()->getConstPointer();
3159       const int *index=getNodalConnectivityIndex()->getConstPointer();
3160       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3161       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3162     }
3163   else
3164     a1=0;
3165 }
3166
3167 /*!
3168  * Second and final unserialization process.
3169  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3170  */
3171 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3172 {
3173   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3174   setMeshDimension(tinyInfo[5]);
3175   if(tinyInfo[7]!=-1)
3176     {
3177       // Connectivity
3178       const int *recvBuffer=a1->getConstPointer();
3179       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3180       myConnecIndex->alloc(tinyInfo[6]+1,1);
3181       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3182       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3183       myConnec->alloc(tinyInfo[7],1);
3184       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3185       setConnectivity(myConnec, myConnecIndex);
3186     }
3187 }
3188
3189
3190
3191 /*!
3192  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3193  * mesh.<br>
3194  * For 1D cells, the returned field contains lengths.<br>
3195  * For 2D cells, the returned field contains areas.<br>
3196  * For 3D cells, the returned field contains volumes.
3197  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3198  *         orientation, i.e. the volume is always positive.
3199  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3200  *         and one time . The caller is to delete this field using decrRef() as it is no
3201  *         more needed.
3202  */
3203 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3204 {
3205   std::string name="MeasureOfMesh_";
3206   name+=getName();
3207   int nbelem=getNumberOfCells();
3208   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3209   field->setName(name);
3210   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3211   array->alloc(nbelem,1);
3212   double *area_vol=array->getPointer();
3213   field->setArray(array) ; array=0;
3214   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3215   field->synchronizeTimeWithMesh();
3216   if(getMeshDimension()!=-1)
3217     {
3218       int ipt;
3219       INTERP_KERNEL::NormalizedCellType type;
3220       int dim_space=getSpaceDimension();
3221       const double *coords=getCoords()->getConstPointer();
3222       const int *connec=getNodalConnectivity()->getConstPointer();
3223       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3224       for(int iel=0;iel<nbelem;iel++)
3225         {
3226           ipt=connec_index[iel];
3227           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3228           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);
3229         }
3230       if(isAbs)
3231         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3232     }
3233   else
3234     {
3235       area_vol[0]=std::numeric_limits<double>::max();
3236     }
3237   return field.retn();
3238 }
3239
3240 /*!
3241  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3242  * mesh.<br>
3243  * For 1D cells, the returned array contains lengths.<br>
3244  * For 2D cells, the returned array contains areas.<br>
3245  * For 3D cells, the returned array contains volumes.
3246  * This method avoids building explicitly a part of \a this mesh to perform the work.
3247  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3248  *         orientation, i.e. the volume is always positive.
3249  *  \param [in] begin - an array of cell ids of interest.
3250  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3251  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3252  *          delete this array using decrRef() as it is no more needed.
3253  * 
3254  *  \if ENABLE_EXAMPLES
3255  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3256  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3257  *  \endif
3258  *  \sa getMeasureField()
3259  */
3260 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3261 {
3262   std::string name="PartMeasureOfMesh_";
3263   name+=getName();
3264   int nbelem=(int)std::distance(begin,end);
3265   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3266   array->setName(name);
3267   array->alloc(nbelem,1);
3268   double *area_vol=array->getPointer();
3269   if(getMeshDimension()!=-1)
3270     {
3271       int ipt;
3272       INTERP_KERNEL::NormalizedCellType type;
3273       int dim_space=getSpaceDimension();
3274       const double *coords=getCoords()->getConstPointer();
3275       const int *connec=getNodalConnectivity()->getConstPointer();
3276       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3277       for(const int *iel=begin;iel!=end;iel++)
3278         {
3279           ipt=connec_index[*iel];
3280           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3281           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3282         }
3283       if(isAbs)
3284         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3285     }
3286   else
3287     {
3288       area_vol[0]=std::numeric_limits<double>::max();
3289     }
3290   return array.retn();
3291 }
3292
3293 /*!
3294  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3295  * \a this one. The returned field contains the dual cell volume for each corresponding
3296  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3297  *  the dual mesh in P1 sens of \a this.<br>
3298  * For 1D cells, the returned field contains lengths.<br>
3299  * For 2D cells, the returned field contains areas.<br>
3300  * For 3D cells, the returned field contains volumes.
3301  * This method is useful to check "P1*" conservative interpolators.
3302  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3303  *         orientation, i.e. the volume is always positive.
3304  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3305  *          nodes and one time. The caller is to delete this array using decrRef() as
3306  *          it is no more needed.
3307  */
3308 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3309 {
3310   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3311   std::string name="MeasureOnNodeOfMesh_";
3312   name+=getName();
3313   int nbNodes=getNumberOfNodes();
3314   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3315   double cst=1./((double)getMeshDimension()+1.);
3316   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3317   array->alloc(nbNodes,1);
3318   double *valsToFill=array->getPointer();
3319   std::fill(valsToFill,valsToFill+nbNodes,0.);
3320   const double *values=tmp->getArray()->getConstPointer();
3321   MCAuto<DataArrayInt> da=DataArrayInt::New();
3322   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3323   getReverseNodalConnectivity(da,daInd);
3324   const int *daPtr=da->getConstPointer();
3325   const int *daIPtr=daInd->getConstPointer();
3326   for(int i=0;i<nbNodes;i++)
3327     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3328       valsToFill[i]+=cst*values[*cell];
3329   ret->setMesh(this);
3330   ret->setArray(array);
3331   return ret.retn();
3332 }
3333
3334 /*!
3335  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3336  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3337  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3338  * and are normalized.
3339  * <br> \a this can be either 
3340  * - a  2D mesh in 2D or 3D space or 
3341  * - an 1D mesh in 2D space.
3342  * 
3343  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3344  *          cells and one time. The caller is to delete this field using decrRef() as
3345  *          it is no more needed.
3346  *  \throw If the nodal connectivity of cells is not defined.
3347  *  \throw If the coordinates array is not set.
3348  *  \throw If the mesh dimension is not set.
3349  *  \throw If the mesh and space dimension is not as specified above.
3350  */
3351 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3352 {
3353   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3354     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3355   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3356   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3357   int nbOfCells=getNumberOfCells();
3358   int nbComp=getMeshDimension()+1;
3359   array->alloc(nbOfCells,nbComp);
3360   double *vals=array->getPointer();
3361   const int *connI=_nodal_connec_index->getConstPointer();
3362   const int *conn=_nodal_connec->getConstPointer();
3363   const double *coords=_coords->getConstPointer();
3364   if(getMeshDimension()==2)
3365     {
3366       if(getSpaceDimension()==3)
3367         {
3368           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3369           const double *locPtr=loc->getConstPointer();
3370           for(int i=0;i<nbOfCells;i++,vals+=3)
3371             {
3372               int offset=connI[i];
3373               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3374               double n=INTERP_KERNEL::norm<3>(vals);
3375               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3376             }
3377         }
3378       else
3379         {
3380           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3381           const double *isAbsPtr=isAbs->getArray()->begin();
3382           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3383             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3384         }
3385     }
3386   else//meshdimension==1
3387     {
3388       double tmp[2];
3389       for(int i=0;i<nbOfCells;i++)
3390         {
3391           int offset=connI[i];
3392           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3393           double n=INTERP_KERNEL::norm<2>(tmp);
3394           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3395           *vals++=-tmp[1];
3396           *vals++=tmp[0];
3397         }
3398     }
3399   ret->setArray(array);
3400   ret->setMesh(this);
3401   ret->synchronizeTimeWithSupport();
3402   return ret.retn();
3403 }
3404
3405 /*!
3406  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3407  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3408  * and are normalized.
3409  * <br> \a this can be either 
3410  * - a  2D mesh in 2D or 3D space or 
3411  * - an 1D mesh in 2D space.
3412  * 
3413  * This method avoids building explicitly a part of \a this mesh to perform the work.
3414  *  \param [in] begin - an array of cell ids of interest.
3415  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3416  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3417  *          cells and one time. The caller is to delete this field using decrRef() as
3418  *          it is no more needed.
3419  *  \throw If the nodal connectivity of cells is not defined.
3420  *  \throw If the coordinates array is not set.
3421  *  \throw If the mesh dimension is not set.
3422  *  \throw If the mesh and space dimension is not as specified above.
3423  *  \sa buildOrthogonalField()
3424  *
3425  *  \if ENABLE_EXAMPLES
3426  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3427  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3428  *  \endif
3429  */
3430 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3431 {
3432   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3433     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3434   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3435   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3436   std::size_t nbelems=std::distance(begin,end);
3437   int nbComp=getMeshDimension()+1;
3438   array->alloc((int)nbelems,nbComp);
3439   double *vals=array->getPointer();
3440   const int *connI=_nodal_connec_index->getConstPointer();
3441   const int *conn=_nodal_connec->getConstPointer();
3442   const double *coords=_coords->getConstPointer();
3443   if(getMeshDimension()==2)
3444     {
3445       if(getSpaceDimension()==3)
3446         {
3447           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3448           const double *locPtr=loc->getConstPointer();
3449           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3450             {
3451               int offset=connI[*i];
3452               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3453               double n=INTERP_KERNEL::norm<3>(vals);
3454               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3455             }
3456         }
3457       else
3458         {
3459           for(std::size_t i=0;i<nbelems;i++)
3460             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3461         }
3462     }
3463   else//meshdimension==1
3464     {
3465       double tmp[2];
3466       for(const int *i=begin;i!=end;i++)
3467         {
3468           int offset=connI[*i];
3469           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3470           double n=INTERP_KERNEL::norm<2>(tmp);
3471           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3472           *vals++=-tmp[1];
3473           *vals++=tmp[0];
3474         }
3475     }
3476   ret->setArray(array);
3477   ret->setMesh(this);
3478   ret->synchronizeTimeWithSupport();
3479   return ret.retn();
3480 }
3481
3482 /*!
3483  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3484  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3485  * and are \b not normalized.
3486  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3487  *          cells and one time. The caller is to delete this field using decrRef() as
3488  *          it is no more needed.
3489  *  \throw If the nodal connectivity of cells is not defined.
3490  *  \throw If the coordinates array is not set.
3491  *  \throw If \a this->getMeshDimension() != 1.
3492  *  \throw If \a this mesh includes cells of type other than SEG2.
3493  */
3494 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3495 {
3496   if(getMeshDimension()!=1)
3497     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3498   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3499     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3500   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3501   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3502   int nbOfCells=getNumberOfCells();
3503   int spaceDim=getSpaceDimension();
3504   array->alloc(nbOfCells,spaceDim);
3505   double *pt=array->getPointer();
3506   const double *coo=getCoords()->getConstPointer();
3507   std::vector<int> conn;
3508   conn.reserve(2);
3509   for(int i=0;i<nbOfCells;i++)
3510     {
3511       conn.resize(0);
3512       getNodeIdsOfCell(i,conn);
3513       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3514     }
3515   ret->setArray(array);
3516   ret->setMesh(this);
3517   ret->synchronizeTimeWithSupport();
3518   return ret.retn();
3519 }
3520
3521 /*!
3522  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3523  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3524  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3525  * from. If a result face is shared by two 3D cells, then the face in included twice in
3526  * the result mesh.
3527  *  \param [in] origin - 3 components of a point defining location of the plane.
3528  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3529  *         must be greater than 1e-6.
3530  *  \param [in] eps - half-thickness of the plane.
3531  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3532  *         producing correspondent 2D cells. The caller is to delete this array
3533  *         using decrRef() as it is no more needed.
3534  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3535  *         not share the node coordinates array with \a this mesh. The caller is to
3536  *         delete this mesh using decrRef() as it is no more needed.  
3537  *  \throw If the coordinates array is not set.
3538  *  \throw If the nodal connectivity of cells is not defined.
3539  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3540  *  \throw If magnitude of \a vec is less than 1e-6.
3541  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3542  *  \throw If \a this includes quadratic cells.
3543  */
3544 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3545 {
3546   checkFullyDefined();
3547   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3548     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3549   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3550   if(candidates->empty())
3551     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3552   std::vector<int> nodes;
3553   DataArrayInt *cellIds1D=0;
3554   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3555   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3556   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3557   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3558   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3559   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3560   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3561   revDesc2=0; revDescIndx2=0;
3562   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3563   revDesc1=0; revDescIndx1=0;
3564   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3565   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3566   //
3567   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3568   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3569     cut3DCurve[*it]=-1;
3570   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3571   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3572   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3573                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3574                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3575   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3576   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3577   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3578   if(cellIds2->empty())
3579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3580   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3581   ret->setCoords(mDesc1->getCoords());
3582   ret->setConnectivity(conn,connI,true);
3583   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3584   return ret.retn();
3585 }
3586
3587 /*!
3588  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3589 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
3590 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3591 the result mesh.
3592  *  \param [in] origin - 3 components of a point defining location of the plane.
3593  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3594  *         must be greater than 1e-6.
3595  *  \param [in] eps - half-thickness of the plane.
3596  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3597  *         producing correspondent segments. The caller is to delete this array
3598  *         using decrRef() as it is no more needed.
3599  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3600  *         mesh in 3D space. This mesh does not share the node coordinates array with
3601  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3602  *         no more needed. 
3603  *  \throw If the coordinates array is not set.
3604  *  \throw If the nodal connectivity of cells is not defined.
3605  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3606  *  \throw If magnitude of \a vec is less than 1e-6.
3607  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3608  *  \throw If \a this includes quadratic cells.
3609  */
3610 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3611 {
3612   checkFullyDefined();
3613   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3614     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3615   MCAuto<DataArrayInt> candidates(getCellIdsCrossingPlane(origin,vec,eps));
3616   if(candidates->empty())
3617     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3618   std::vector<int> nodes;
3619   DataArrayInt *cellIds1D(0);
3620   MCAuto<MEDCouplingUMesh> subMesh(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3621   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3622   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
3623   MCAuto<MEDCouplingUMesh> mDesc1(subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3624   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3625   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3626   //
3627   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3628   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3629     cut3DCurve[*it]=-1;
3630   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3631   int ncellsSub=subMesh->getNumberOfCells();
3632   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3633   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3634                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3635                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3636   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3637   conn->alloc(0,1);
3638   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3639   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3640   for(int i=0;i<ncellsSub;i++)
3641     {
3642       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3643         {
3644           if(cut3DSurf[i].first!=-2)
3645             {
3646               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3647               connI->pushBackSilent(conn->getNumberOfTuples());
3648               cellIds2->pushBackSilent(i);
3649             }
3650           else
3651             {
3652               int cellId3DSurf=cut3DSurf[i].second;
3653               int offset=nodalI[cellId3DSurf]+1;
3654               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3655               for(int j=0;j<nbOfEdges;j++)
3656                 {
3657                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3658                   connI->pushBackSilent(conn->getNumberOfTuples());
3659                   cellIds2->pushBackSilent(cellId3DSurf);
3660                 }
3661             }
3662         }
3663     }
3664   if(cellIds2->empty())
3665     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3666   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3667   ret->setCoords(mDesc1->getCoords());
3668   ret->setConnectivity(conn,connI,true);
3669   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3670   return ret.retn();
3671 }
3672
3673 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::clipSingle3DCellByPlane(const double origin[3], const double vec[3], double eps) const
3674 {
3675   checkFullyDefined();
3676   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3677     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3678   if(getNumberOfCells()!=1)
3679     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works only on mesh containing exactly one cell !");
3680   //
3681   std::vector<int> nodes;
3682   findNodesOnPlane(origin,vec,eps,nodes);
3683   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),desc2(DataArrayInt::New()),descIndx1(DataArrayInt::New()),descIndx2(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDesc2(DataArrayInt::New()),revDescIndx1(DataArrayInt::New()),revDescIndx2(DataArrayInt::New());
3684   MCAuto<MEDCouplingUMesh> mDesc2(buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2));//meshDim==2 spaceDim==3
3685   revDesc2=0; revDescIndx2=0;
3686   MCAuto<MEDCouplingUMesh> mDesc1(mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3687   revDesc1=0; revDescIndx1=0;
3688   DataArrayInt *cellIds1D(0);
3689   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3690   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3691   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3692   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3693     cut3DCurve[*it]=-1;
3694   bool sameNbNodes;
3695   {
3696     int oldNbNodes(mDesc1->getNumberOfNodes());
3697     mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3698     sameNbNodes=(mDesc1->getNumberOfNodes()==oldNbNodes);
3699   }
3700   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3701   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->begin(),mDesc2->getNodalConnectivityIndex()->begin(),
3702                               mDesc1->getNodalConnectivity()->begin(),mDesc1->getNodalConnectivityIndex()->begin(),
3703                               desc1->begin(),descIndx1->begin(),cut3DSurf);
3704   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New());
3705   connI->pushBackSilent(0); conn->alloc(0,1);
3706   {
3707     MCAuto<DataArrayInt> cellIds2(DataArrayInt::New()); cellIds2->alloc(0,1);
3708     assemblyForSplitFrom3DSurf(cut3DSurf,desc2->begin(),descIndx2->begin(),conn,connI,cellIds2);
3709     if(cellIds2->empty())
3710       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3711   }
3712   std::vector<std::vector<int> > res;
3713   buildSubCellsFromCut(cut3DSurf,desc2->begin(),descIndx2->begin(),mDesc1->getCoords()->begin(),eps,res);
3714   std::size_t sz(res.size());
3715   if(res.size()==mDesc1->getNumberOfCells() && sameNbNodes)
3716     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane : cell is not clipped !");
3717   for(std::size_t i=0;i<sz;i++)
3718     {
3719       conn->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
3720       conn->insertAtTheEnd(res[i].begin(),res[i].end());
3721       connI->pushBackSilent(conn->getNumberOfTuples());
3722     }
3723   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
3724   ret->setCoords(mDesc1->getCoords());
3725   ret->setConnectivity(conn,connI,true);
3726   int nbCellsRet(ret->getNumberOfCells());
3727   //
3728   MCAuto<DataArrayDouble> vec2(DataArrayDouble::New()); vec2->alloc(1,3); std::copy(vec,vec+3,vec2->getPointer());
3729   MCAuto<MEDCouplingFieldDouble> ortho(ret->buildOrthogonalField());
3730   MCAuto<DataArrayDouble> ortho2(ortho->getArray()->selectByTupleIdSafeSlice(0,1,1));
3731   MCAuto<DataArrayDouble> dott(DataArrayDouble::Dot(ortho2,vec2));
3732   MCAuto<DataArrayDouble> ccm(ret->computeCellCenterOfMass());
3733   MCAuto<DataArrayDouble> occm;
3734   {
3735     MCAuto<DataArrayDouble> pt(DataArrayDouble::New()); pt->alloc(1,3); std::copy(origin,origin+3,pt->getPointer());
3736     occm=DataArrayDouble::Substract(ccm,pt);
3737   }
3738   vec2=DataArrayDouble::New(); vec2->alloc(nbCellsRet,3);
3739   vec2->setPartOfValuesSimple1(vec[0],0,nbCellsRet,1,0,1,1); vec2->setPartOfValuesSimple1(vec[1],0,nbCellsRet,1,1,2,1); vec2->setPartOfValuesSimple1(vec[2],0,nbCellsRet,1,2,3,1);
3740   MCAuto<DataArrayDouble> dott2(DataArrayDouble::Dot(occm,vec2));
3741   //
3742   const int *cPtr(ret->getNodalConnectivity()->begin()),*ciPtr(ret->getNodalConnectivityIndex()->begin());
3743   MCAuto<MEDCouplingUMesh> ret2(MEDCouplingUMesh::New("Clip3D",3));
3744   ret2->setCoords(mDesc1->getCoords());
3745   MCAuto<DataArrayInt> conn2(DataArrayInt::New()),conn2I(DataArrayInt::New());
3746   conn2I->pushBackSilent(0); conn2->alloc(0,1);
3747   std::vector<int> cell0(1,(int)INTERP_KERNEL::NORM_POLYHED);
3748   std::vector<int> cell1(1,(int)INTERP_KERNEL::NORM_POLYHED);
3749   if(dott->getIJ(0,0)>0)
3750     {
3751       cell0.insert(cell0.end(),cPtr+1,cPtr+ciPtr[1]);
3752       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell1,cell1.end()));
3753     }
3754   else
3755     {
3756       cell1.insert(cell1.end(),cPtr+1,cPtr+ciPtr[1]);
3757       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell0,cell0.end()));
3758     }
3759   for(int i=1;i<nbCellsRet;i++)
3760     {
3761       if(dott2->getIJ(i,0)<0)
3762         {
3763           if(ciPtr[i+1]-ciPtr[i]>=4)
3764             {
3765               cell0.push_back(-1);
3766               cell0.insert(cell0.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3767             }
3768         }
3769       else
3770         {
3771           if(ciPtr[i+1]-ciPtr[i]>=4)
3772             {
3773               cell1.push_back(-1);
3774               cell1.insert(cell1.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3775             }
3776         }
3777     }
3778   conn2->insertAtTheEnd(cell0.begin(),cell0.end());
3779   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3780   conn2->insertAtTheEnd(cell1.begin(),cell1.end());
3781   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3782   ret2->setConnectivity(conn2,conn2I,true);
3783   ret2->checkConsistencyLight();
3784   ret2->orientCorrectlyPolyhedrons();
3785   return ret2;
3786 }
3787
3788 /*!
3789  * Finds cells whose bounding boxes intersect a given plane.
3790  *  \param [in] origin - 3 components of a point defining location of the plane.
3791  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3792  *         must be greater than 1e-6.
3793  *  \param [in] eps - half-thickness of the plane.
3794  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3795  *         cells. The caller is to delete this array using decrRef() as it is no more
3796  *         needed.
3797  *  \throw If the coordinates array is not set.
3798  *  \throw If the nodal connectivity of cells is not defined.
3799  *  \throw If \a this->getSpaceDimension() != 3.
3800  *  \throw If magnitude of \a vec is less than 1e-6.
3801  *  \sa buildSlice3D()
3802  */
3803 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3804 {
3805   checkFullyDefined();
3806   if(getSpaceDimension()!=3)
3807     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3808   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3809   if(normm<1e-6)
3810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3811   double vec2[3];
3812   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3813   double angle=acos(vec[2]/normm);
3814   MCAuto<DataArrayInt> cellIds;
3815   double bbox[6];
3816   if(angle>eps)
3817     {
3818       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3819       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3820       if(normm2/normm>1e-6)
3821         DataArrayDouble::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer(),coo->getPointer());
3822       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3823       mw->setCoords(coo);
3824       mw->getBoundingBox(bbox);
3825       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3826       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3827     }
3828   else
3829     {
3830       getBoundingBox(bbox);
3831       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3832       cellIds=getCellsInBoundingBox(bbox,eps);
3833     }
3834   return cellIds.retn();
3835 }
3836
3837 /*!
3838  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3839  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3840  * No consideration of coordinate is done by this method.
3841  * 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)
3842  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
3843  */
3844 bool MEDCouplingUMesh::isContiguous1D() const
3845 {
3846   if(getMeshDimension()!=1)
3847     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3848   int nbCells=getNumberOfCells();
3849   if(nbCells<1)
3850     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3851   const int *connI(_nodal_connec_index->begin()),*conn(_nodal_connec->begin());
3852   int ref=conn[connI[0]+2];
3853   for(int i=1;i<nbCells;i++)
3854     {
3855       if(conn[connI[i]+1]!=ref)
3856         return false;
3857       ref=conn[connI[i]+2];
3858     }
3859   return true;
3860 }
3861
3862 /*!
3863  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3864  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3865  * \param pt reference point of the line
3866  * \param v normalized director vector of the line
3867  * \param eps max precision before throwing an exception
3868  * \param res output of size this->getNumberOfCells
3869  */
3870 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3871 {
3872   if(getMeshDimension()!=1)
3873     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3874   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3875     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3876   if(getSpaceDimension()!=3)
3877     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3878   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3879   const double *fPtr=f->getArray()->getConstPointer();
3880   double tmp[3];
3881   for(std::size_t i=0;i<getNumberOfCells();i++)
3882     {
3883       const double *tmp1=fPtr+3*i;
3884       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3885       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3886       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3887       double n1=INTERP_KERNEL::norm<3>(tmp);
3888       n1/=INTERP_KERNEL::norm<3>(tmp1);
3889       if(n1>eps)
3890         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3891     }
3892   const double *coo=getCoords()->getConstPointer();
3893   for(int i=0;i<getNumberOfNodes();i++)
3894     {
3895       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3896       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3897       res[i]=std::accumulate(tmp,tmp+3,0.);
3898     }
3899 }
3900
3901 /*!
3902  * 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. 
3903  * \a this is expected to be a mesh so that its space dimension is equal to its
3904  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3905  * 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).
3906  *
3907  * 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
3908  * 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).
3909  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3910  *
3911  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3912  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3913  *
3914  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3915  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3916  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3917  * \return the positive value of the distance.
3918  * \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
3919  * dimension - 1.
3920  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3921  */
3922 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3923 {
3924   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3925   if(meshDim!=spaceDim-1)
3926     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3927   if(meshDim!=2 && meshDim!=1)
3928     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3929   checkFullyDefined();
3930   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3931     { 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()); }
3932   DataArrayInt *ret1=0;
3933   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3934   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3935   MCAuto<DataArrayInt> ret1Safe(ret1);
3936   cellId=*ret1Safe->begin();
3937   return *ret0->begin();
3938 }
3939
3940 /*!
3941  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3942  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3943  * 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
3944  * 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).
3945  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3946  * 
3947  * \a this is expected to be a mesh so that its space dimension is equal to its
3948  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3949  * 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).
3950  *
3951  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3952  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3953  *
3954  * \param [in] pts the list of points in which each tuple represents a point
3955  * \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.
3956  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3957  * \throw if number of components of \a pts is not equal to the space dimension.
3958  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3959  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3960  */
3961 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3962 {
3963   if(!pts)
3964     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3965   pts->checkAllocated();
3966   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3967   if(meshDim!=spaceDim-1)
3968     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3969   if(meshDim!=2 && meshDim!=1)
3970     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3971   if((int)pts->getNumberOfComponents()!=spaceDim)
3972     {
3973       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3974       throw INTERP_KERNEL::Exception(oss.str());
3975     }
3976   checkFullyDefined();
3977   int nbCells=getNumberOfCells();
3978   if(nbCells==0)
3979     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3980   int nbOfPts=pts->getNumberOfTuples();
3981   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3982   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3983   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3984   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3985   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3986   const double *bbox(bboxArr->begin());
3987   switch(spaceDim)
3988   {
3989     case 3:
3990       {
3991         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3992         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3993           {
3994             double x=std::numeric_limits<double>::max();
3995             std::vector<int> elems;
3996             myTree.getMinDistanceOfMax(ptsPtr,x);
3997             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3998             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3999           }
4000         break;
4001       }
4002     case 2:
4003       {
4004         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4005         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4006           {
4007             double x=std::numeric_limits<double>::max();
4008             std::vector<int> elems;
4009             myTree.getMinDistanceOfMax(ptsPtr,x);
4010             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4011             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4012           }
4013         break;
4014       }
4015     default:
4016       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4017   }
4018   cellIds=ret1.retn();
4019   return ret0.retn();
4020 }
4021
4022 /// @cond INTERNAL
4023
4024 /// @endcond
4025
4026 /*!
4027  * Finds cells in contact with a ball (i.e. a point with precision). 
4028  * 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.
4029  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4030  *
4031  * \warning This method is suitable if the caller intends to evaluate only one
4032  *          point, for more points getCellsContainingPoints() is recommended as it is
4033  *          faster. 
4034  *  \param [in] pos - array of coordinates of the ball central point.
4035  *  \param [in] eps - ball radius.
4036  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4037  *         if there are no such cells.
4038  *  \throw If the coordinates array is not set.
4039  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4040  */
4041 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4042 {
4043   std::vector<int> elts;
4044   getCellsContainingPoint(pos,eps,elts);
4045   if(elts.empty())
4046     return -1;
4047   return elts.front();
4048 }
4049
4050 /*!
4051  * Finds cells in contact with a ball (i.e. a point with precision).
4052  * 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.
4053  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4054  * \warning This method is suitable if the caller intends to evaluate only one
4055  *          point, for more points getCellsContainingPoints() is recommended as it is
4056  *          faster. 
4057  *  \param [in] pos - array of coordinates of the ball central point.
4058  *  \param [in] eps - ball radius.
4059  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4060  *         before inserting ids.
4061  *  \throw If the coordinates array is not set.
4062  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4063  *
4064  *  \if ENABLE_EXAMPLES
4065  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4066  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4067  *  \endif
4068  */
4069 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4070 {
4071   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4072   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4073   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4074 }
4075
4076 /*!
4077  * Finds cells in contact with several balls (i.e. points with precision).
4078  * This method is an extension of getCellContainingPoint() and
4079  * getCellsContainingPoint() for the case of multiple points.
4080  * 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.
4081  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4082  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4083  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4084  *         this->getSpaceDimension() * \a nbOfPoints 
4085  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4086  *  \param [in] eps - radius of balls (i.e. the precision).
4087  *  \param [out] elts - vector returning ids of found cells.
4088  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4089  *         dividing cell ids in \a elts into groups each referring to one
4090  *         point. Its every element (except the last one) is an index pointing to the
4091  *         first id of a group of cells. For example cells in contact with the *i*-th
4092  *         point are described by following range of indices:
4093  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4094  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4095  *         Number of cells in contact with the *i*-th point is
4096  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4097  *  \throw If the coordinates array is not set.
4098  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4099  *
4100  *  \if ENABLE_EXAMPLES
4101  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4102  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4103  *  \endif
4104  */
4105 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4106                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4107 {
4108   int spaceDim=getSpaceDimension();
4109   int mDim=getMeshDimension();
4110   if(spaceDim==3)
4111     {
4112       if(mDim==3)
4113         {
4114           const double *coords=_coords->getConstPointer();
4115           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4116         }
4117       /*else if(mDim==2)
4118         {
4119
4120         }*/
4121       else
4122         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4123     }
4124   else if(spaceDim==2)
4125     {
4126       if(mDim==2)
4127         {
4128           const double *coords=_coords->getConstPointer();
4129           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4130         }
4131       else
4132         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4133     }
4134   else if(spaceDim==1)
4135     {
4136       if(mDim==1)
4137         {
4138           const double *coords=_coords->getConstPointer();
4139           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4140         }
4141       else
4142         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4143     }
4144   else
4145     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4146 }
4147
4148 /*!
4149  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4150  * least two its edges intersect each other anywhere except their extremities. An
4151  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4152  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4153  *         cleared before filling in.
4154  *  \param [in] eps - precision.
4155  *  \throw If \a this->getMeshDimension() != 2.
4156  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4157  */
4158 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4159 {
4160   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4161   if(getMeshDimension()!=2)
4162     throw INTERP_KERNEL::Exception(msg);
4163   int spaceDim=getSpaceDimension();
4164   if(spaceDim!=2 && spaceDim!=3)
4165     throw INTERP_KERNEL::Exception(msg);
4166   const int *conn=_nodal_connec->getConstPointer();
4167   const int *connI=_nodal_connec_index->getConstPointer();
4168   int nbOfCells=getNumberOfCells();
4169   std::vector<double> cell2DinS2;
4170   for(int i=0;i<nbOfCells;i++)
4171     {
4172       int offset=connI[i];
4173       int nbOfNodesForCell=connI[i+1]-offset-1;
4174       if(nbOfNodesForCell<=3)
4175         continue;
4176       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4177       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4178       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4179         cells.push_back(i);
4180       cell2DinS2.clear();
4181     }
4182 }
4183
4184 /*!
4185  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4186  *
4187  * 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.
4188  * 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.
4189  * 
4190  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4191  * This convex envelop is computed using Jarvis march algorithm.
4192  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4193  * 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)
4194  * 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.
4195  *
4196  * \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.
4197  * \sa MEDCouplingUMesh::colinearize2D
4198  */
4199 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4200 {
4201   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4202     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4203   checkFullyDefined();
4204   const double *coords=getCoords()->getConstPointer();
4205   int nbOfCells=getNumberOfCells();
4206   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4207   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4208   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4209   int *workIndexOut=nodalConnecIndexOut->getPointer();
4210   *workIndexOut=0;
4211   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4212   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4213   std::set<INTERP_KERNEL::NormalizedCellType> types;
4214   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4215   isChanged->alloc(0,1);
4216   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4217     {
4218       int pos=nodalConnecOut->getNumberOfTuples();
4219       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4220         isChanged->pushBackSilent(i);
4221       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4222       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4223     }
4224   if(isChanged->empty())
4225     return 0;
4226   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4227   _types=types;
4228   return isChanged.retn();
4229 }
4230
4231 /*!
4232  * This method is \b NOT const because it can modify \a this.
4233  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4234  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4235  * \param policy specifies the type of extrusion chosen:
4236  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4237  *   will be repeated to build each level
4238  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4239  *   the 3 preceding points of the 1D mesh. The center of the arc is the center of rotation for each level, the rotation is done
4240  *   along an axis normal to the plane containing the arc, and finally the angle of rotation is defined by the first two points on the
4241  *   arc.
4242  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4243  */
4244 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4245 {
4246   checkFullyDefined();
4247   mesh1D->checkFullyDefined();
4248   if(!mesh1D->isContiguous1D())
4249     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4250   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4251     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4252   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4253     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4254   if(mesh1D->getMeshDimension()!=1)
4255     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4256   bool isQuad=false;
4257   if(isPresenceOfQuadratic())
4258     {
4259       if(mesh1D->isFullyQuadratic())
4260         isQuad=true;
4261       else
4262         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4263     }
4264   int oldNbOfNodes(getNumberOfNodes());
4265   MCAuto<DataArrayDouble> newCoords;
4266   switch(policy)
4267   {
4268     case 0:
4269       {
4270         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4271         break;
4272       }
4273     case 1:
4274       {
4275         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4276         break;
4277       }
4278     default:
4279       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4280   }
4281   setCoords(newCoords);
4282   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4283   updateTime();
4284   return ret.retn();
4285 }
4286
4287
4288 /*!
4289  * Checks if \a this mesh is constituted by only quadratic cells.
4290  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4291  *  \throw If the coordinates array is not set.
4292  *  \throw If the nodal connectivity of cells is not defined.
4293  */
4294 bool MEDCouplingUMesh::isFullyQuadratic() const
4295 {
4296   checkFullyDefined();
4297   bool ret=true;
4298   int nbOfCells=getNumberOfCells();
4299   for(int i=0;i<nbOfCells && ret;i++)
4300     {
4301       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4302       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4303       ret=cm.isQuadratic();
4304     }
4305   return ret;
4306 }
4307
4308 /*!
4309  * Checks if \a this mesh includes any quadratic cell.
4310  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4311  *  \throw If the coordinates array is not set.
4312  *  \throw If the nodal connectivity of cells is not defined.
4313  */
4314 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4315 {
4316   checkFullyDefined();
4317   bool ret=false;
4318   int nbOfCells=getNumberOfCells();
4319   for(int i=0;i<nbOfCells && !ret;i++)
4320     {
4321       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4322       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4323       ret=cm.isQuadratic();
4324     }
4325   return ret;
4326 }
4327
4328 /*!
4329  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4330  * this mesh, it remains unchanged.
4331  *  \throw If the coordinates array is not set.
4332  *  \throw If the nodal connectivity of cells is not defined.
4333  */
4334 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4335 {
4336   checkFullyDefined();
4337   int nbOfCells(getNumberOfCells());
4338   int delta=0;
4339   const int *iciptr=_nodal_connec_index->begin();
4340   for(int i=0;i<nbOfCells;i++)
4341     {
4342       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4343       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4344       if(cm.isQuadratic())
4345         {
4346           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4347           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4348           if(!cml.isDynamic())
4349             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4350           else
4351             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4352         }
4353     }
4354   if(delta==0)
4355     return ;
4356   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4357   const int *icptr(_nodal_connec->begin());
4358   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
4359   newConnI->alloc(nbOfCells+1,1);
4360   int *ocptr(newConn->getPointer()),*ociptr(newConnI->getPointer());
4361   *ociptr=0;
4362   _types.clear();
4363   for(int i=0;i<nbOfCells;i++,ociptr++)
4364     {
4365       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4366       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4367       if(!cm.isQuadratic())
4368         {
4369           _types.insert(type);
4370           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4371           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4372         }
4373       else
4374         {
4375           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4376           _types.insert(typel);
4377           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4378           int newNbOfNodes=cml.getNumberOfNodes();
4379           if(cml.isDynamic())
4380             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4381           *ocptr++=(int)typel;
4382           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4383           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4384         }
4385     }
4386   setConnectivity(newConn,newConnI,false);
4387 }
4388
4389 /*!
4390  * This method converts all linear cell in \a this to quadratic one.
4391  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4392  * 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)
4393  * 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.
4394  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4395  * end of the existing coordinates.
4396  * 
4397  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4398  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4399  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4400  * 
4401  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4402  *
4403  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4404  */
4405 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4406 {
4407   DataArrayInt *conn=0,*connI=0;
4408   DataArrayDouble *coords=0;
4409   std::set<INTERP_KERNEL::NormalizedCellType> types;
4410   checkFullyDefined();
4411   MCAuto<DataArrayInt> ret,connSafe,connISafe;
4412   MCAuto<DataArrayDouble> coordsSafe;
4413   int meshDim=getMeshDimension();
4414   switch(conversionType)
4415   {
4416     case 0:
4417       switch(meshDim)
4418       {
4419         case 1:
4420           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4421           connSafe=conn; connISafe=connI; coordsSafe=coords;
4422           break;
4423         case 2:
4424           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4425           connSafe=conn; connISafe=connI; coordsSafe=coords;
4426           break;
4427         case 3:
4428           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4429           connSafe=conn; connISafe=connI; coordsSafe=coords;
4430           break;
4431         default:
4432           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4433       }
4434       break;
4435         case 1:
4436           {
4437             switch(meshDim)
4438             {
4439               case 1:
4440                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4441                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4442                 break;
4443               case 2:
4444                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4445                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4446                 break;
4447               case 3:
4448                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4449                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4450                 break;
4451               default:
4452                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4453             }
4454             break;
4455           }
4456         default:
4457           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4458   }
4459   setConnectivity(connSafe,connISafe,false);
4460   _types=types;
4461   setCoords(coordsSafe);
4462   return ret.retn();
4463 }
4464
4465 /*!
4466  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
4467  * so that the number of cells remains the same. Quadratic faces are converted to
4468  * polygons. This method works only for 2D meshes in
4469  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
4470  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
4471  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4472  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
4473  *         a polylinized edge constituting the input polygon.
4474  *  \throw If the coordinates array is not set.
4475  *  \throw If the nodal connectivity of cells is not defined.
4476  *  \throw If \a this->getMeshDimension() != 2.
4477  *  \throw If \a this->getSpaceDimension() != 2.
4478  */
4479 void MEDCouplingUMesh::tessellate2D(double eps)
4480 {
4481   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
4482   if(spaceDim!=2)
4483     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
4484   switch(meshDim)
4485     {
4486     case 1:
4487       return tessellate2DCurveInternal(eps);
4488     case 2:
4489       return tessellate2DInternal(eps);
4490     default:
4491       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
4492     }
4493 }
4494 /*!
4495  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
4496  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4497  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
4498  *         a sub-divided edge.
4499  *  \throw If the coordinates array is not set.
4500  *  \throw If the nodal connectivity of cells is not defined.
4501  *  \throw If \a this->getMeshDimension() != 1.
4502  *  \throw If \a this->getSpaceDimension() != 2.
4503  */
4504
4505 #if 0
4506 /*!
4507  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
4508  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
4509  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
4510  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
4511  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
4512  * This method can be seen as the opposite method of colinearize2D.
4513  * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end
4514  * to avoid to modify the numbering of existing nodes.
4515  *
4516  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
4517  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
4518  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
4519  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
4520  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
4521  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
4522  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
4523  *
4524  * \sa buildDescendingConnectivity2
4525  */
4526 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
4527                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
4528 {
4529   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
4530     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
4531   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
4532   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
4533     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
4534   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
4535     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
4536   //DataArrayInt *out0(0),*outi0(0);
4537   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
4538   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
4539   //out0s=out0s->buildUnique(); out0s->sort(true);
4540 }
4541 #endif
4542
4543
4544 /*!
4545  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
4546  * In addition, returns an array mapping new cells to old ones. <br>
4547  * This method typically increases the number of cells in \a this mesh
4548  * but the number of nodes remains \b unchanged.
4549  * That's why the 3D splitting policies
4550  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
4551  *  \param [in] policy - specifies a pattern used for splitting.
4552  * The semantic of \a policy is:
4553  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
4554  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
4555  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4556  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4557  *
4558  *
4559  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
4560  *          an id of old cell producing it. The caller is to delete this array using
4561  *         decrRef() as it is no more needed.
4562  *
4563  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
4564  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
4565  *          and \a this->getMeshDimension() != 3. 
4566  *  \throw If \a policy is not one of the four discussed above.
4567  *  \throw If the nodal connectivity of cells is not defined.
4568  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
4569  */
4570 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
4571 {
4572   switch(policy)
4573   {
4574     case 0:
4575       return simplexizePol0();
4576     case 1:
4577       return simplexizePol1();
4578     case (int) INTERP_KERNEL::PLANAR_FACE_5:
4579         return simplexizePlanarFace5();
4580     case (int) INTERP_KERNEL::PLANAR_FACE_6:
4581         return simplexizePlanarFace6();
4582     default:
4583       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)");
4584   }
4585 }
4586
4587 /*!
4588  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
4589  * - 1D: INTERP_KERNEL::NORM_SEG2
4590  * - 2D: INTERP_KERNEL::NORM_TRI3
4591  * - 3D: INTERP_KERNEL::NORM_TETRA4.
4592  *
4593  * This method is useful for users that need to use P1 field services as
4594  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
4595  * All these methods need mesh support containing only simplex cells.
4596  *  \return bool - \c true if there are only simplex cells in \a this mesh.
4597  *  \throw If the coordinates array is not set.
4598  *  \throw If the nodal connectivity of cells is not defined.
4599  *  \throw If \a this->getMeshDimension() < 1.
4600  */
4601 bool MEDCouplingUMesh::areOnlySimplexCells() const
4602 {
4603   checkFullyDefined();
4604   int mdim=getMeshDimension();
4605   if(mdim<1 || mdim>3)
4606     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
4607   int nbCells=getNumberOfCells();
4608   const int *conn=_nodal_connec->begin();
4609   const int *connI=_nodal_connec_index->begin();
4610   for(int i=0;i<nbCells;i++)
4611     {
4612       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4613       if(!cm.isSimplex())
4614         return false;
4615     }
4616   return true;
4617 }
4618
4619
4620
4621 /*!
4622  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
4623  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
4624  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
4625  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
4626  * so it can be useful to call mergeNodes() before calling this method.
4627  *  \throw If \a this->getMeshDimension() <= 1.
4628  *  \throw If the coordinates array is not set.
4629  *  \throw If the nodal connectivity of cells is not defined.
4630  */
4631 void MEDCouplingUMesh::convertDegeneratedCells()
4632 {
4633   checkFullyDefined();
4634   if(getMeshDimension()<=1)
4635     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4636   int nbOfCells=getNumberOfCells();
4637   if(nbOfCells<1)
4638     return ;
4639   int initMeshLgth=getNodalConnectivityArrayLen();
4640   int *conn=_nodal_connec->getPointer();
4641   int *index=_nodal_connec_index->getPointer();
4642   int posOfCurCell=0;
4643   int newPos=0;
4644   int lgthOfCurCell;
4645   for(int i=0;i<nbOfCells;i++)
4646     {
4647       lgthOfCurCell=index[i+1]-posOfCurCell;
4648       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4649       int newLgth;
4650       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4651                                                                                                      conn+newPos+1,newLgth);
4652       conn[newPos]=newType;
4653       newPos+=newLgth+1;
4654       posOfCurCell=index[i+1];
4655       index[i+1]=newPos;
4656     }
4657   if(newPos!=initMeshLgth)
4658     _nodal_connec->reAlloc(newPos);
4659   computeTypes();
4660 }
4661
4662 /*!
4663  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
4664  * A cell is considered to be oriented correctly if an angle between its
4665  * normal vector and a given vector is less than \c PI / \c 2.
4666  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4667  *         cells. 
4668  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4669  *         checked.
4670  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4671  *         is not cleared before filling in.
4672  *  \throw If \a this->getMeshDimension() != 2.
4673  *  \throw If \a this->getSpaceDimension() != 3.
4674  *
4675  *  \if ENABLE_EXAMPLES
4676  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4677  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4678  *  \endif
4679  */
4680 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
4681 {
4682   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4683     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4684   int nbOfCells=getNumberOfCells();
4685   const int *conn=_nodal_connec->begin();
4686   const int *connI=_nodal_connec_index->begin();
4687   const double *coordsPtr=_coords->begin();
4688   for(int i=0;i<nbOfCells;i++)
4689     {
4690       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4691       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4692         {
4693           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4694           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4695             cells.push_back(i);
4696         }
4697     }
4698 }
4699
4700 /*!
4701  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
4702  * considered to be oriented correctly if an angle between its normal vector and a
4703  * given vector is less than \c PI / \c 2. 
4704  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4705  *         cells. 
4706  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4707  *         checked.
4708  *  \throw If \a this->getMeshDimension() != 2.
4709  *  \throw If \a this->getSpaceDimension() != 3.
4710  *
4711  *  \if ENABLE_EXAMPLES
4712  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4713  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4714  *  \endif
4715  *
4716  *  \sa changeOrientationOfCells
4717  */
4718 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
4719 {
4720   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4721     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
4722   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4723   const int *connI(_nodal_connec_index->begin());
4724   const double *coordsPtr(_coords->begin());
4725   bool isModified(false);
4726   for(int i=0;i<nbOfCells;i++)
4727     {
4728       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4729       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4730         {
4731           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4732           bool isQuadratic(cm.isQuadratic());
4733           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4734             {
4735               isModified=true;
4736               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4737             }
4738         }
4739     }
4740   if(isModified)
4741     _nodal_connec->declareAsNew();
4742   updateTime();
4743 }
4744
4745 /*!
4746  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
4747  *
4748  * \sa orientCorrectly2DCells
4749  */
4750 void MEDCouplingUMesh::changeOrientationOfCells()
4751 {
4752   int mdim(getMeshDimension());
4753   if(mdim!=2 && mdim!=1)
4754     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
4755   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4756   const int *connI(_nodal_connec_index->begin());
4757   if(mdim==2)
4758     {//2D
4759       for(int i=0;i<nbOfCells;i++)
4760         {
4761           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4762           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4763           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4764         }
4765     }
4766   else
4767     {//1D
4768       for(int i=0;i<nbOfCells;i++)
4769         {
4770           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4771           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4772           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4773         }
4774     }
4775 }
4776
4777 /*!
4778  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
4779  * oriented facets. The normal vector of the facet should point out of the cell.
4780  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4781  *         is not cleared before filling in.
4782  *  \throw If \a this->getMeshDimension() != 3.
4783  *  \throw If \a this->getSpaceDimension() != 3.
4784  *  \throw If the coordinates array is not set.
4785  *  \throw If the nodal connectivity of cells is not defined.
4786  *
4787  *  \if ENABLE_EXAMPLES
4788  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4789  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4790  *  \endif
4791  */
4792 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
4793 {
4794   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4795     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
4796   int nbOfCells=getNumberOfCells();
4797   const int *conn=_nodal_connec->begin();
4798   const int *connI=_nodal_connec_index->begin();
4799   const double *coordsPtr=_coords->begin();
4800   for(int i=0;i<nbOfCells;i++)
4801     {
4802       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4803       if(type==INTERP_KERNEL::NORM_POLYHED)
4804         {
4805           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4806             cells.push_back(i);
4807         }
4808     }
4809 }
4810
4811 /*!
4812  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
4813  * out of the cell. 
4814  *  \throw If \a this->getMeshDimension() != 3.
4815  *  \throw If \a this->getSpaceDimension() != 3.
4816  *  \throw If the coordinates array is not set.
4817  *  \throw If the nodal connectivity of cells is not defined.
4818  *  \throw If the reparation fails.
4819  *
4820  *  \if ENABLE_EXAMPLES
4821  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4822  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4823  *  \endif
4824  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4825  */
4826 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
4827 {
4828   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4829     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
4830   int nbOfCells=getNumberOfCells();
4831   int *conn=_nodal_connec->getPointer();
4832   const int *connI=_nodal_connec_index->begin();
4833   const double *coordsPtr=_coords->begin();
4834   for(int i=0;i<nbOfCells;i++)
4835     {
4836       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4837       if(type==INTERP_KERNEL::NORM_POLYHED)
4838         {
4839           try
4840           {
4841               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4842                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4843           }
4844           catch(INTERP_KERNEL::Exception& e)
4845           {
4846               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
4847               throw INTERP_KERNEL::Exception(oss.str());
4848           }
4849         }
4850     }
4851   updateTime();
4852 }
4853
4854 /*!
4855  * This method invert orientation of all cells in \a this. 
4856  * After calling this method the absolute value of measure of cells in \a this are the same than before calling.
4857  * This method only operates on the connectivity so coordinates are not touched at all.
4858  */
4859 void MEDCouplingUMesh::invertOrientationOfAllCells()
4860 {
4861   checkConnectivityFullyDefined();
4862   std::set<INTERP_KERNEL::NormalizedCellType> gts(getAllGeoTypes());
4863   int *conn(_nodal_connec->getPointer());
4864   const int *conni(_nodal_connec_index->begin());
4865   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator gt=gts.begin();gt!=gts.end();gt++)
4866     {
4867       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::OrientationInverter> oi(INTERP_KERNEL::OrientationInverter::BuildInstanceFrom(*gt));
4868       MCAuto<DataArrayInt> cwt(giveCellsWithType(*gt));
4869       for(const int *it=cwt->begin();it!=cwt->end();it++)
4870         oi->operate(conn+conni[*it]+1,conn+conni[*it+1]);
4871     }
4872   updateTime();
4873 }
4874
4875 /*!
4876  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
4877  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
4878  * according to which the first facet of the cell should be oriented to have the normal vector
4879  * pointing out of cell.
4880  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
4881  *         cells. The caller is to delete this array using decrRef() as it is no more
4882  *         needed. 
4883  *  \throw If \a this->getMeshDimension() != 3.
4884  *  \throw If \a this->getSpaceDimension() != 3.
4885  *  \throw If the coordinates array is not set.
4886  *  \throw If the nodal connectivity of cells is not defined.
4887  *
4888  *  \if ENABLE_EXAMPLES
4889  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
4890  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
4891  *  \endif
4892  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4893  */
4894 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
4895 {
4896   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
4897   if(getMeshDimension()!=3)
4898     throw INTERP_KERNEL::Exception(msg);
4899   int spaceDim=getSpaceDimension();
4900   if(spaceDim!=3)
4901     throw INTERP_KERNEL::Exception(msg);
4902   //
4903   int nbOfCells=getNumberOfCells();
4904   int *conn=_nodal_connec->getPointer();
4905   const int *connI=_nodal_connec_index->begin();
4906   const double *coo=getCoords()->begin();
4907   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
4908   for(int i=0;i<nbOfCells;i++)
4909     {
4910       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4911       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
4912         {
4913           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
4914             {
4915               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4916               cells->pushBackSilent(i);
4917             }
4918         }
4919     }
4920   return cells.retn();
4921 }
4922
4923 /*!
4924  * This method is a faster method to correct orientation of all 3D cells in \a this.
4925  * 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.
4926  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
4927  * 
4928  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
4929  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
4930  */
4931 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
4932 {
4933   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4934     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
4935   int nbOfCells=getNumberOfCells();
4936   int *conn=_nodal_connec->getPointer();
4937   const int *connI=_nodal_connec_index->begin();
4938   const double *coordsPtr=_coords->begin();
4939   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4940   for(int i=0;i<nbOfCells;i++)
4941     {
4942       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4943       switch(type)
4944       {
4945         case INTERP_KERNEL::NORM_TETRA4:
4946           {
4947             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4948               {
4949                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
4950                 ret->pushBackSilent(i);
4951               }
4952             break;
4953           }
4954         case INTERP_KERNEL::NORM_PYRA5:
4955           {
4956             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4957               {
4958                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
4959                 ret->pushBackSilent(i);
4960               }
4961             break;
4962           }
4963         case INTERP_KERNEL::NORM_PENTA6:
4964         case INTERP_KERNEL::NORM_HEXA8:
4965         case INTERP_KERNEL::NORM_HEXGP12:
4966           {
4967             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4968               {
4969                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4970                 ret->pushBackSilent(i);
4971               }
4972             break;
4973           }
4974         case INTERP_KERNEL::NORM_POLYHED:
4975           {
4976             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4977               {
4978                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4979                 ret->pushBackSilent(i);
4980               }
4981             break;
4982           }
4983         default:
4984           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 !");
4985       }
4986     }
4987   updateTime();
4988   return ret.retn();
4989 }
4990
4991 /*!
4992  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
4993  * If it is not the case an exception will be thrown.
4994  * This method is fast because the first cell of \a this is used to compute the plane.
4995  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
4996  * \param pos output of size at least 3 used to store a point owned of searched plane.
4997  */
4998 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
4999 {
5000   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5001     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5002   const int *conn=_nodal_connec->begin();
5003   const int *connI=_nodal_connec_index->begin();
5004   const double *coordsPtr=_coords->begin();
5005   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5006   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5007 }
5008
5009 /*!
5010  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5011  * cells. Currently cells of the following types are treated:
5012  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5013  * For a cell of other type an exception is thrown.
5014  * Space dimension of a 2D mesh can be either 2 or 3.
5015  * The Edge Ratio of a cell \f$t\f$ is: 
5016  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5017  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5018  *  the smallest edge lengths of \f$t\f$.
5019  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5020  *          cells and one time, lying on \a this mesh. The caller is to delete this
5021  *          field using decrRef() as it is no more needed. 
5022  *  \throw If the coordinates array is not set.
5023  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5024  *  \throw If the connectivity data array has more than one component.
5025  *  \throw If the connectivity data array has a named component.
5026  *  \throw If the connectivity index data array has more than one component.
5027  *  \throw If the connectivity index data array has a named component.
5028  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5029  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5030  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5031  */
5032 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
5033 {
5034   checkConsistencyLight();
5035   int spaceDim=getSpaceDimension();
5036   int meshDim=getMeshDimension();
5037   if(spaceDim!=2 && spaceDim!=3)
5038     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5039   if(meshDim!=2 && meshDim!=3)
5040     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5041   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5042   ret->setMesh(this);
5043   int nbOfCells=getNumberOfCells();
5044   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5045   arr->alloc(nbOfCells,1);
5046   double *pt=arr->getPointer();
5047   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5048   const int *conn=_nodal_connec->begin();
5049   const int *connI=_nodal_connec_index->begin();
5050   const double *coo=_coords->begin();
5051   double tmp[12];
5052   for(int i=0;i<nbOfCells;i++,pt++)
5053     {
5054       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5055       switch(t)
5056       {
5057         case INTERP_KERNEL::NORM_TRI3:
5058           {
5059             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5060             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5061             break;
5062           }
5063         case INTERP_KERNEL::NORM_QUAD4:
5064           {
5065             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5066             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5067             break;
5068           }
5069         case INTERP_KERNEL::NORM_TETRA4:
5070           {
5071             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5072             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5073             break;
5074           }
5075         default:
5076           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5077       }
5078       conn+=connI[i+1]-connI[i];
5079     }
5080   ret->setName("EdgeRatio");
5081   ret->synchronizeTimeWithSupport();
5082   return ret.retn();
5083 }
5084
5085 /*!
5086  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5087  * cells. Currently cells of the following types are treated:
5088  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5089  * For a cell of other type an exception is thrown.
5090  * Space dimension of a 2D mesh can be either 2 or 3.
5091  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5092  *          cells and one time, lying on \a this mesh. The caller is to delete this
5093  *          field using decrRef() as it is no more needed. 
5094  *  \throw If the coordinates array is not set.
5095  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5096  *  \throw If the connectivity data array has more than one component.
5097  *  \throw If the connectivity data array has a named component.
5098  *  \throw If the connectivity index data array has more than one component.
5099  *  \throw If the connectivity index data array has a named component.
5100  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5101  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5102  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5103  */
5104 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
5105 {
5106   checkConsistencyLight();
5107   int spaceDim=getSpaceDimension();
5108   int meshDim=getMeshDimension();
5109   if(spaceDim!=2 && spaceDim!=3)
5110     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5111   if(meshDim!=2 && meshDim!=3)
5112     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5113   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5114   ret->setMesh(this);
5115   int nbOfCells=getNumberOfCells();
5116   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5117   arr->alloc(nbOfCells,1);
5118   double *pt=arr->getPointer();
5119   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5120   const int *conn=_nodal_connec->begin();
5121   const int *connI=_nodal_connec_index->begin();
5122   const double *coo=_coords->begin();
5123   double tmp[12];
5124   for(int i=0;i<nbOfCells;i++,pt++)
5125     {
5126       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5127       switch(t)
5128       {
5129         case INTERP_KERNEL::NORM_TRI3:
5130           {
5131             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5132             *pt=INTERP_KERNEL::triAspectRatio(tmp);
5133             break;
5134           }
5135         case INTERP_KERNEL::NORM_QUAD4:
5136           {
5137             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5138             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5139             break;
5140           }
5141         case INTERP_KERNEL::NORM_TETRA4:
5142           {
5143             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5144             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5145             break;
5146           }
5147         default:
5148           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5149       }
5150       conn+=connI[i+1]-connI[i];
5151     }
5152   ret->setName("AspectRatio");
5153   ret->synchronizeTimeWithSupport();
5154   return ret.retn();
5155 }
5156
5157 /*!
5158  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
5159  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
5160  * in 3D space. Currently only cells of the following types are
5161  * treated: INTERP_KERNEL::NORM_QUAD4.
5162  * For a cell of other type an exception is thrown.
5163  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
5164  * Defining
5165  * \f$t=\vec{da}\times\vec{ab}\f$,
5166  * \f$u=\vec{ab}\times\vec{bc}\f$
5167  * \f$v=\vec{bc}\times\vec{cd}\f$
5168  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
5169  *  \f[
5170  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
5171  *  \f]
5172  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5173  *          cells and one time, lying on \a this mesh. The caller is to delete this
5174  *          field using decrRef() as it is no more needed. 
5175  *  \throw If the coordinates array is not set.
5176  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5177  *  \throw If the connectivity data array has more than one component.
5178  *  \throw If the connectivity data array has a named component.
5179  *  \throw If the connectivity index data array has more than one component.
5180  *  \throw If the connectivity index data array has a named component.
5181  *  \throw If \a this->getMeshDimension() != 2.
5182  *  \throw If \a this->getSpaceDimension() != 3.
5183  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5184  */
5185 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
5186 {
5187   checkConsistencyLight();
5188   int spaceDim=getSpaceDimension();
5189   int meshDim=getMeshDimension();
5190   if(spaceDim!=3)
5191     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5192   if(meshDim!=2)
5193     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5194   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5195   ret->setMesh(this);
5196   int nbOfCells=getNumberOfCells();
5197   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5198   arr->alloc(nbOfCells,1);
5199   double *pt=arr->getPointer();
5200   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5201   const int *conn=_nodal_connec->begin();
5202   const int *connI=_nodal_connec_index->begin();
5203   const double *coo=_coords->begin();
5204   double tmp[12];
5205   for(int i=0;i<nbOfCells;i++,pt++)
5206     {
5207       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5208       switch(t)
5209       {
5210         case INTERP_KERNEL::NORM_QUAD4:
5211           {
5212             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5213             *pt=INTERP_KERNEL::quadWarp(tmp);
5214             break;
5215           }
5216         default:
5217           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5218       }
5219       conn+=connI[i+1]-connI[i];
5220     }
5221   ret->setName("Warp");
5222   ret->synchronizeTimeWithSupport();
5223   return ret.retn();
5224 }
5225
5226
5227 /*!
5228  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
5229  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
5230  * treated: INTERP_KERNEL::NORM_QUAD4.
5231  * The skew is computed as follow for a quad with points (a,b,c,d): let
5232  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
5233  * then the skew is computed as:
5234  *  \f[
5235  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
5236  *  \f]
5237  *
5238  * For a cell of other type an exception is thrown.
5239  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5240  *          cells and one time, lying on \a this mesh. The caller is to delete this
5241  *          field using decrRef() as it is no more needed. 
5242  *  \throw If the coordinates array is not set.
5243  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5244  *  \throw If the connectivity data array has more than one component.
5245  *  \throw If the connectivity data array has a named component.
5246  *  \throw If the connectivity index data array has more than one component.
5247  *  \throw If the connectivity index data array has a named component.
5248  *  \throw If \a this->getMeshDimension() != 2.
5249  *  \throw If \a this->getSpaceDimension() != 3.
5250  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5251  */
5252 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
5253 {
5254   checkConsistencyLight();
5255   int spaceDim=getSpaceDimension();
5256   int meshDim=getMeshDimension();
5257   if(spaceDim!=3)
5258     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5259   if(meshDim!=2)
5260     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5261   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5262   ret->setMesh(this);
5263   int nbOfCells=getNumberOfCells();
5264   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5265   arr->alloc(nbOfCells,1);
5266   double *pt=arr->getPointer();
5267   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5268   const int *conn=_nodal_connec->begin();
5269   const int *connI=_nodal_connec_index->begin();
5270   const double *coo=_coords->begin();
5271   double tmp[12];
5272   for(int i=0;i<nbOfCells;i++,pt++)
5273     {
5274       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5275       switch(t)
5276       {
5277         case INTERP_KERNEL::NORM_QUAD4:
5278           {
5279             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5280             *pt=INTERP_KERNEL::quadSkew(tmp);
5281             break;
5282           }
5283         default:
5284           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5285       }
5286       conn+=connI[i+1]-connI[i];
5287     }
5288   ret->setName("Skew");
5289   ret->synchronizeTimeWithSupport();
5290   return ret.retn();
5291 }
5292
5293 /*!
5294  * Returns the cell field giving for each cell in \a this its diameter. Diameter means the max length of all possible SEG2 in the cell.
5295  *
5296  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
5297  *
5298  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
5299  */
5300 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
5301 {
5302   checkConsistencyLight();
5303   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
5304   ret->setMesh(this);
5305   std::set<INTERP_KERNEL::NormalizedCellType> types;
5306   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
5307   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
5308   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
5309   arr->alloc(nbCells,1);
5310   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
5311     {
5312       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
5313       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
5314       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
5315     }
5316   ret->setArray(arr);
5317   ret->setName("Diameter");
5318   return ret.retn();
5319 }
5320
5321 /*!
5322  * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax).
5323  * 
5324  * \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)
5325  *                         For all other cases this input parameter is ignored.
5326  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5327  * 
5328  * \throw If \a this is not fully set (coordinates and connectivity).
5329  * \throw If a cell in \a this has no valid nodeId.
5330  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5331  */
5332 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
5333 {
5334   int mDim(getMeshDimension()),sDim(getSpaceDimension());
5335   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.
5336     return getBoundingBoxForBBTreeFast();
5337   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
5338     {
5339       bool presenceOfQuadratic(false);
5340       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
5341         {
5342           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
5343           if(cm.isQuadratic())
5344             presenceOfQuadratic=true;
5345         }
5346       if(!presenceOfQuadratic)
5347         return getBoundingBoxForBBTreeFast();
5348       if(mDim==2 && sDim==2)
5349         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
5350       else
5351         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
5352     }
5353   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) !");
5354 }
5355
5356 /*!
5357  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
5358  * So meshes having quadratic cells the computed bounding boxes can be invalid !
5359  * 
5360  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5361  * 
5362  * \throw If \a this is not fully set (coordinates and connectivity).
5363  * \throw If a cell in \a this has no valid nodeId.
5364  */
5365 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
5366 {
5367   checkFullyDefined();
5368   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
5369   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5370   double *bbox(ret->getPointer());
5371   for(int i=0;i<nbOfCells*spaceDim;i++)
5372     {
5373       bbox[2*i]=std::numeric_limits<double>::max();
5374       bbox[2*i+1]=-std::numeric_limits<double>::max();
5375     }
5376   const double *coordsPtr(_coords->begin());
5377   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5378   for(int i=0;i<nbOfCells;i++)
5379     {
5380       int offset=connI[i]+1;
5381       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
5382       for(int j=0;j<nbOfNodesForCell;j++)
5383         {
5384           int nodeId=conn[offset+j];
5385           if(nodeId>=0 && nodeId<nbOfNodes)
5386             {
5387               for(int k=0;k<spaceDim;k++)
5388                 {
5389                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5390                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5391                 }
5392               kk++;
5393             }
5394         }
5395       if(kk==0)
5396         {
5397           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
5398           throw INTERP_KERNEL::Exception(oss.str());
5399         }
5400     }
5401   return ret.retn();
5402 }
5403
5404 /*!
5405  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
5406  * useful for 2D meshes having quadratic cells
5407  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5408  * the two extremities of the arc of circle).
5409  * 
5410  * \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)
5411  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5412  * \throw If \a this is not fully defined.
5413  * \throw If \a this is not a mesh with meshDimension equal to 2.
5414  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5415  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
5416  */
5417 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
5418 {
5419   checkFullyDefined();
5420   INTERP_KERNEL::QuadraticPlanarArcDetectionPrecision arcPrec(arcDetEps);
5421
5422   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5423   if(spaceDim!=2 || mDim!=2)
5424     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!");
5425   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5426   double *bbox(ret->getPointer());
5427   const double *coords(_coords->begin());
5428   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5429   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5430     {
5431       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5432       int sz(connI[1]-connI[0]-1);
5433       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5434       INTERP_KERNEL::QuadraticPolygon *pol(0);
5435       for(int j=0;j<sz;j++)
5436         {
5437           int nodeId(conn[*connI+1+j]);
5438           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5439         }
5440       if(!cm.isQuadratic())
5441         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
5442       else
5443         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
5444       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
5445       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
5446     }
5447   return ret.retn();
5448 }
5449
5450 /*!
5451  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
5452  * useful for 2D meshes having quadratic cells
5453  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5454  * the two extremities of the arc of circle).
5455  * 
5456  * \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)
5457  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5458  * \throw If \a this is not fully defined.
5459  * \throw If \a this is not a mesh with meshDimension equal to 1.
5460  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5461  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5462  */
5463 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
5464 {
5465   checkFullyDefined();
5466   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5467   if(spaceDim!=2 || mDim!=1)
5468     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!");
5469   INTERP_KERNEL::QuadraticPlanarArcDetectionPrecision arcPrec(arcDetEps);
5470   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5471   double *bbox(ret->getPointer());
5472   const double *coords(_coords->begin());
5473   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5474   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5475     {
5476       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5477       int sz(connI[1]-connI[0]-1);
5478       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5479       INTERP_KERNEL::Edge *edge(0);
5480       for(int j=0;j<sz;j++)
5481         {
5482           int nodeId(conn[*connI+1+j]);
5483           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5484         }
5485       if(!cm.isQuadratic())
5486         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
5487       else
5488         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
5489       const INTERP_KERNEL::Bounds& b(edge->getBounds());
5490       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
5491     }
5492   return ret.retn();
5493 }
5494
5495 /// @cond INTERNAL
5496
5497 namespace MEDCouplingImpl
5498 {
5499   class ConnReader
5500   {
5501   public:
5502     ConnReader(const int *c, int val):_conn(c),_val(val) { }
5503     bool operator() (const int& pos) { return _conn[pos]!=_val; }
5504   private:
5505     const int *_conn;
5506     int _val;
5507   };
5508
5509   class ConnReader2
5510   {
5511   public:
5512     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5513     bool operator() (const int& pos) { return _conn[pos]==_val; }
5514   private:
5515     const int *_conn;
5516     int _val;
5517   };
5518 }
5519
5520 /// @endcond
5521
5522 /*!
5523  * This method expects that \a this is sorted by types. If not an exception will be thrown.
5524  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5525  * \a this is composed in cell types.
5526  * The returned array is of size 3*n where n is the number of different types present in \a this. 
5527  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
5528  * This parameter is kept only for compatibility with other methode listed above.
5529  */
5530 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
5531 {
5532   checkConnectivityFullyDefined();
5533   const int *conn=_nodal_connec->begin();
5534   const int *connI=_nodal_connec_index->begin();
5535   const int *work=connI;
5536   int nbOfCells=getNumberOfCells();
5537   std::size_t n=getAllGeoTypes().size();
5538   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
5539   std::set<INTERP_KERNEL::NormalizedCellType> types;
5540   for(std::size_t i=0;work!=connI+nbOfCells;i++)
5541     {
5542       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5543       if(types.find(typ)!=types.end())
5544         {
5545           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5546           oss << " is not contiguous !";
5547           throw INTERP_KERNEL::Exception(oss.str());
5548         }
5549       types.insert(typ);
5550       ret[3*i]=typ;
5551       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
5552       ret[3*i+1]=(int)std::distance(work,work2);
5553       work=work2;
5554     }
5555   return ret;
5556 }
5557
5558 /*!
5559  * This method is used to check that this has contiguous cell type in same order than described in \a code.
5560  * only for types cell, type node is not managed.
5561  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
5562  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5563  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5564  * If 2 or more same geometric type is in \a code and exception is thrown too.
5565  *
5566  * This method firstly checks
5567  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5568  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5569  * an exception is thrown too.
5570  * 
5571  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
5572  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
5573  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5574  */
5575 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
5576 {
5577   if(code.empty())
5578     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5579   std::size_t sz=code.size();
5580   std::size_t n=sz/3;
5581   if(sz%3!=0)
5582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5583   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5584   int nb=0;
5585   bool isNoPflUsed=true;
5586   for(std::size_t i=0;i<n;i++)
5587     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5588       {
5589         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5590         nb+=code[3*i+1];
5591         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5592           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5593         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
5594       }
5595   if(types.size()!=n)
5596     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5597   if(isNoPflUsed)
5598     {
5599       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5600         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5601       if(types.size()==_types.size())
5602         return 0;
5603     }
5604   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5605   ret->alloc(nb,1);
5606   int *retPtr=ret->getPointer();
5607   const int *connI=_nodal_connec_index->begin();
5608   const int *conn=_nodal_connec->begin();
5609   int nbOfCells=getNumberOfCells();
5610   const int *i=connI;
5611   int kk=0;
5612   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5613     {
5614       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
5615       int offset=(int)std::distance(connI,i);
5616       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
5617       int nbOfCellsOfCurType=(int)std::distance(i,j);
5618       if(code[3*kk+2]==-1)
5619         for(int k=0;k<nbOfCellsOfCurType;k++)
5620           *retPtr++=k+offset;
5621       else
5622         {
5623           int idInIdsPerType=code[3*kk+2];
5624           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
5625             {
5626               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
5627               if(zePfl)
5628                 {
5629                   zePfl->checkAllocated();
5630                   if(zePfl->getNumberOfComponents()==1)
5631                     {
5632                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
5633                         {
5634                           if(*k>=0 && *k<nbOfCellsOfCurType)
5635                             *retPtr=(*k)+offset;
5636                           else
5637                             {
5638                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
5639                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
5640                               throw INTERP_KERNEL::Exception(oss.str());
5641                             }
5642                         }
5643                     }
5644                   else
5645                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
5646                 }
5647               else
5648                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
5649             }
5650           else
5651             {
5652               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
5653               oss << " should be in [0," << idsPerType.size() << ") !";
5654               throw INTERP_KERNEL::Exception(oss.str());
5655             }
5656         }
5657       i=j;
5658     }
5659   return ret.retn();
5660 }
5661
5662 /*!
5663  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
5664  * 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.
5665  * 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.
5666  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
5667  * 
5668  * \param [in] profile
5669  * \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.
5670  * \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,
5671  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5672  * \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.
5673  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5674  * \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
5675  */
5676 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
5677 {
5678   if(!profile)
5679     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
5680   if(profile->getNumberOfComponents()!=1)
5681     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5682   checkConnectivityFullyDefined();
5683   const int *conn=_nodal_connec->begin();
5684   const int *connI=_nodal_connec_index->begin();
5685   int nbOfCells=getNumberOfCells();
5686   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5687   std::vector<int> typeRangeVals(1);
5688   for(const int *i=connI;i!=connI+nbOfCells;)
5689     {
5690       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5691       if(std::find(types.begin(),types.end(),curType)!=types.end())
5692         {
5693           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5694         }
5695       types.push_back(curType);
5696       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5697       typeRangeVals.push_back((int)std::distance(connI,i));
5698     }
5699   //
5700   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5701   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5702   MCAuto<DataArrayInt> tmp0=castArr;
5703   MCAuto<DataArrayInt> tmp1=rankInsideCast;
5704   MCAuto<DataArrayInt> tmp2=castsPresent;
5705   //
5706   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5707   code.resize(3*nbOfCastsFinal);
5708   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
5709   std::vector< MCAuto<DataArrayInt> > idsPerType2;
5710   for(int i=0;i<nbOfCastsFinal;i++)
5711     {
5712       int castId=castsPresent->getIJ(i,0);
5713       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
5714       idsInPflPerType2.push_back(tmp3);
5715       code[3*i]=(int)types[castId];
5716       code[3*i+1]=tmp3->getNumberOfTuples();
5717       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->begin(),tmp3->begin()+tmp3->getNumberOfTuples());
5718       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
5719         {
5720           tmp4->copyStringInfoFrom(*profile);
5721           idsPerType2.push_back(tmp4);
5722           code[3*i+2]=(int)idsPerType2.size()-1;
5723         }
5724       else
5725         {
5726           code[3*i+2]=-1;
5727         }
5728     }
5729   std::size_t sz2=idsInPflPerType2.size();
5730   idsInPflPerType.resize(sz2);
5731   for(std::size_t i=0;i<sz2;i++)
5732     {
5733       DataArrayInt *locDa=idsInPflPerType2[i];
5734       locDa->incrRef();
5735       idsInPflPerType[i]=locDa;
5736     }
5737   std::size_t sz=idsPerType2.size();
5738   idsPerType.resize(sz);
5739   for(std::size_t i=0;i<sz;i++)
5740     {
5741       DataArrayInt *locDa=idsPerType2[i];
5742       locDa->incrRef();
5743       idsPerType[i]=locDa;
5744     }
5745 }
5746
5747 /*!
5748  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5749  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5750  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5751  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as MEDCoupling::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.
5752  */
5753 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
5754 {
5755   checkFullyDefined();
5756   nM1LevMesh->checkFullyDefined();
5757   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5758     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5759   if(_coords!=nM1LevMesh->getCoords())
5760     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5761   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
5762   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
5763   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5764   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5765   desc->transformWithIndArr(ret0->begin(),ret0->begin()+ret0->getNbOfElems());
5766   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5767   tmp->setConnectivity(tmp0,tmp1);
5768   tmp->renumberCells(ret0->begin(),false);
5769   revDesc=tmp->getNodalConnectivity();
5770   revDescIndx=tmp->getNodalConnectivityIndex();
5771   DataArrayInt *ret=0;
5772   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5773     {
5774       int tmp2;
5775       ret->getMaxValue(tmp2);
5776       ret->decrRef();
5777       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5778       throw INTERP_KERNEL::Exception(oss.str());
5779     }
5780   nM1LevMeshIds=ret;
5781   //
5782   revDesc->incrRef();
5783   revDescIndx->incrRef();
5784   ret1->incrRef();
5785   ret0->incrRef();
5786   meshnM1Old2New=ret0;
5787   return ret1;
5788 }
5789
5790 /*!
5791  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
5792  * necessary for writing the mesh to MED file. Additionally returns a permutation array
5793  * in "Old to New" mode.
5794  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
5795  *          this array using decrRef() as it is no more needed.
5796  *  \throw If the nodal connectivity of cells is not defined.
5797  */
5798 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
5799 {
5800   checkConnectivityFullyDefined();
5801   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
5802   renumberCells(ret->begin(),false);
5803   return ret.retn();
5804 }
5805
5806 /*!
5807  * This methods checks that cells are sorted by their types.
5808  * This method makes asumption (no check) that connectivity is correctly set before calling.
5809  */
5810 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5811 {
5812   checkFullyDefined();
5813   const int *conn=_nodal_connec->begin();
5814   const int *connI=_nodal_connec_index->begin();
5815   int nbOfCells=getNumberOfCells();
5816   std::set<INTERP_KERNEL::NormalizedCellType> types;
5817   for(const int *i=connI;i!=connI+nbOfCells;)
5818     {
5819       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5820       if(types.find(curType)!=types.end())
5821         return false;
5822       types.insert(curType);
5823       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5824     }
5825   return true;
5826 }
5827
5828 /*!
5829  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
5830  * The geometric type order is specified by MED file.
5831  * 
5832  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
5833  */
5834 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
5835 {
5836   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5837 }
5838
5839 /*!
5840  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5841  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
5842  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
5843  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
5844  */
5845 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5846 {
5847   checkFullyDefined();
5848   const int *conn=_nodal_connec->begin();
5849   const int *connI=_nodal_connec_index->begin();
5850   int nbOfCells=getNumberOfCells();
5851   if(nbOfCells==0)
5852     return true;
5853   int lastPos=-1;
5854   std::set<INTERP_KERNEL::NormalizedCellType> sg;
5855   for(const int *i=connI;i!=connI+nbOfCells;)
5856     {
5857       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5858       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
5859       if(isTypeExists!=orderEnd)
5860         {
5861           int pos=(int)std::distance(orderBg,isTypeExists);
5862           if(pos<=lastPos)
5863             return false;
5864           lastPos=pos;
5865           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5866         }
5867       else
5868         {
5869           if(sg.find(curType)==sg.end())
5870             {
5871               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5872               sg.insert(curType);
5873             }
5874           else
5875             return false;
5876         }
5877     }
5878   return true;
5879 }
5880
5881 /*!
5882  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5883  * 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
5884  * 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'.
5885  */
5886 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
5887 {
5888   checkConnectivityFullyDefined();
5889   int nbOfCells=getNumberOfCells();
5890   const int *conn=_nodal_connec->begin();
5891   const int *connI=_nodal_connec_index->begin();
5892   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
5893   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
5894   tmpa->alloc(nbOfCells,1);
5895   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
5896   tmpb->fillWithZero();
5897   int *tmp=tmpa->getPointer();
5898   int *tmp2=tmpb->getPointer();
5899   for(const int *i=connI;i!=connI+nbOfCells;i++)
5900     {
5901       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
5902       if(where!=orderEnd)
5903         {
5904           int pos=(int)std::distance(orderBg,where);
5905           tmp2[pos]++;
5906           tmp[std::distance(connI,i)]=pos;
5907         }
5908       else
5909         {
5910           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
5911           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
5912           oss << " has a type " << cm.getRepr() << " not in input array of type !";
5913           throw INTERP_KERNEL::Exception(oss.str());
5914         }
5915     }
5916   nbPerType=tmpb.retn();
5917   return tmpa.retn();
5918 }
5919
5920 /*!
5921  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
5922  *
5923  * \return a new object containing the old to new correspondance.
5924  *
5925  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5926  */
5927 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
5928 {
5929   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5930 }
5931
5932 /*!
5933  * 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.
5934  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
5935  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
5936  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
5937  */
5938 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5939 {
5940   DataArrayInt *nbPerType=0;
5941   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
5942   nbPerType->decrRef();
5943   return tmpa->buildPermArrPerLevel();
5944 }
5945
5946 /*!
5947  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
5948  * The number of cells remains unchanged after the call of this method.
5949  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
5950  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5951  *
5952  * \return the array giving the correspondance old to new.
5953  */
5954 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
5955 {
5956   checkFullyDefined();
5957   computeTypes();
5958   const int *conn=_nodal_connec->begin();
5959   const int *connI=_nodal_connec_index->begin();
5960   int nbOfCells=getNumberOfCells();
5961   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5962   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
5963     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
5964       {
5965         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5966         types.push_back(curType);
5967         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
5968       }
5969   DataArrayInt *ret=DataArrayInt::New();
5970   ret->alloc(nbOfCells,1);
5971   int *retPtr=ret->getPointer();
5972   std::fill(retPtr,retPtr+nbOfCells,-1);
5973   int newCellId=0;
5974   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5975     {
5976       for(const int *i=connI;i!=connI+nbOfCells;i++)
5977         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5978           retPtr[std::distance(connI,i)]=newCellId++;
5979     }
5980   renumberCells(retPtr,false);
5981   return ret;
5982 }
5983
5984 /*!
5985  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
5986  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
5987  * This method makes asumption that connectivity is correctly set before calling.
5988  */
5989 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
5990 {
5991   checkConnectivityFullyDefined();
5992   const int *conn=_nodal_connec->begin();
5993   const int *connI=_nodal_connec_index->begin();
5994   int nbOfCells=getNumberOfCells();
5995   std::vector<MEDCouplingUMesh *> ret;
5996   for(const int *i=connI;i!=connI+nbOfCells;)
5997     {
5998       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5999       int beginCellId=(int)std::distance(connI,i);
6000       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
6001       int endCellId=(int)std::distance(connI,i);
6002       int sz=endCellId-beginCellId;
6003       int *cells=new int[sz];
6004       for(int j=0;j<sz;j++)
6005         cells[j]=beginCellId+j;
6006       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6007       delete [] cells;
6008       ret.push_back(m);
6009     }
6010   return ret;
6011 }
6012
6013 /*!
6014  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6015  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6016  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6017  *
6018  * \return a newly allocated instance, that the caller must manage.
6019  * \throw If \a this contains more than one geometric type.
6020  * \throw If the nodal connectivity of \a this is not fully defined.
6021  * \throw If the internal data is not coherent.
6022  */
6023 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6024 {
6025   checkConnectivityFullyDefined();
6026   if(_types.size()!=1)
6027     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6028   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6029   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6030   ret->setCoords(getCoords());
6031   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6032   if(retC)
6033     {
6034       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6035       retC->setNodalConnectivity(c);
6036     }
6037   else
6038     {
6039       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6040       if(!retD)
6041         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6042       DataArrayInt *c=0,*ci=0;
6043       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6044       MCAuto<DataArrayInt> cs(c),cis(ci);
6045       retD->setNodalConnectivity(cs,cis);
6046     }
6047   return ret.retn();
6048 }
6049
6050 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6051 {
6052   checkConnectivityFullyDefined();
6053   if(_types.size()!=1)
6054     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6055   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6056   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6057   if(cm.isDynamic())
6058     {
6059       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6060       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6061       throw INTERP_KERNEL::Exception(oss.str());
6062     }
6063   int nbCells=getNumberOfCells();
6064   int typi=(int)typ;
6065   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6066   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6067   int *outPtr=connOut->getPointer();
6068   const int *conn=_nodal_connec->begin();
6069   const int *connI=_nodal_connec_index->begin();
6070   nbNodesPerCell++;
6071   for(int i=0;i<nbCells;i++,connI++)
6072     {
6073       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6074         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6075       else
6076         {
6077           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 << ") !";
6078           throw INTERP_KERNEL::Exception(oss.str());
6079         }
6080     }
6081   return connOut.retn();
6082 }
6083
6084 /*!
6085  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
6086  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
6087  * \param nodalConn
6088  * \param nodalConnI
6089  */
6090 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
6091 {
6092   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
6093   checkConnectivityFullyDefined();
6094   if(_types.size()!=1)
6095     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6096   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6097   if(lgth<nbCells)
6098     throw INTERP_KERNEL::Exception(msg0);
6099   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6100   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6101   int *cp(c->getPointer()),*cip(ci->getPointer());
6102   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6103   cip[0]=0;
6104   for(int i=0;i<nbCells;i++,cip++,incip++)
6105     {
6106       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6107       int delta(stop-strt);
6108       if(delta>=1)
6109         {
6110           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6111             cp=std::copy(incp+strt,incp+stop,cp);
6112           else
6113             throw INTERP_KERNEL::Exception(msg0);
6114         }
6115       else
6116         throw INTERP_KERNEL::Exception(msg0);
6117       cip[1]=cip[0]+delta;
6118     }
6119   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6120 }
6121
6122 /*!
6123  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6124  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6125  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6126  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6127  * are not used here to avoid the build of big permutation array.
6128  *
6129  * \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
6130  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6131  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6132  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6133  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6134  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6135  * \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
6136  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6137  */
6138 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6139                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6140                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
6141 {
6142   std::vector<const MEDCouplingUMesh *> ms2;
6143   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6144     if(*it)
6145       {
6146         (*it)->checkConnectivityFullyDefined();
6147         ms2.push_back(*it);
6148       }
6149   if(ms2.empty())
6150     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6151   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6152   int meshDim=ms2[0]->getMeshDimension();
6153   std::vector<const MEDCouplingUMesh *> m1ssm;
6154   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
6155   //
6156   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6157   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
6158   int fake=0,rk=0;
6159   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6160   ret1->alloc(0,1); ret2->alloc(0,1);
6161   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6162     {
6163       if(meshDim!=(*it)->getMeshDimension())
6164         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6165       if(refCoo!=(*it)->getCoords())
6166         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6167       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6168       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6169       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
6170       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6171         {
6172           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6173           m1ssmSingleAuto.push_back(singleCell);
6174           m1ssmSingle.push_back(singleCell);
6175           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6176         }
6177     }
6178   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6179   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6180   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6181   for(std::size_t i=0;i<m1ssm.size();i++)
6182     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6183   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6184   szOfCellGrpOfSameType=ret1->renumber(renum->begin());
6185   idInMsOfCellGrpOfSameType=ret2->renumber(renum->begin());
6186   return ret0.retn();
6187 }
6188
6189 /*!
6190  * This method returns a newly created DataArrayInt instance.
6191  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6192  */
6193 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
6194 {
6195   checkFullyDefined();
6196   const int *conn=_nodal_connec->begin();
6197   const int *connIndex=_nodal_connec_index->begin();
6198   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6199   for(const int *w=begin;w!=end;w++)
6200     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6201       ret->pushBackSilent(*w);
6202   return ret.retn();
6203 }
6204
6205 /*!
6206  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6207  * are in [0:getNumberOfCells())
6208  */
6209 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
6210 {
6211   checkFullyDefined();
6212   const int *conn=_nodal_connec->begin();
6213   const int *connI=_nodal_connec_index->begin();
6214   int nbOfCells=getNumberOfCells();
6215   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
6216   int *tmp=new int[nbOfCells];
6217   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6218     {
6219       int j=0;
6220       for(const int *i=connI;i!=connI+nbOfCells;i++)
6221         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6222           tmp[std::distance(connI,i)]=j++;
6223     }
6224   DataArrayInt *ret=DataArrayInt::New();
6225   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6226   ret->copyStringInfoFrom(*da);
6227   int *retPtr=ret->getPointer();
6228   const int *daPtr=da->begin();
6229   int nbOfElems=da->getNbOfElems();
6230   for(int k=0;k<nbOfElems;k++)
6231     retPtr[k]=tmp[daPtr[k]];
6232   delete [] tmp;
6233   return ret;
6234 }
6235
6236 /*!
6237  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6238  * This method \b works \b for mesh sorted by type.
6239  * cells whose ids is in 'idsPerGeoType' array.
6240  * This method conserves coords and name of mesh.
6241  */
6242 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6243 {
6244   std::vector<int> code=getDistributionOfTypes();
6245   std::size_t nOfTypesInThis=code.size()/3;
6246   int sz=0,szOfType=0;
6247   for(std::size_t i=0;i<nOfTypesInThis;i++)
6248     {
6249       if(code[3*i]!=type)
6250         sz+=code[3*i+1];
6251       else
6252         szOfType=code[3*i+1];
6253     }
6254   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6255     if(*work<0 || *work>=szOfType)
6256       {
6257         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6258         oss << ". It should be in [0," << szOfType << ") !";
6259         throw INTERP_KERNEL::Exception(oss.str());
6260       }
6261   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6262   int *idsPtr=idsTokeep->getPointer();
6263   int offset=0;
6264   for(std::size_t i=0;i<nOfTypesInThis;i++)
6265     {
6266       if(code[3*i]!=type)
6267         for(int j=0;j<code[3*i+1];j++)
6268           *idsPtr++=offset+j;
6269       else
6270         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6271       offset+=code[3*i+1];
6272     }
6273   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6274   ret->copyTinyInfoFrom(this);
6275   return ret.retn();
6276 }
6277
6278 /*!
6279  * This method returns a vector of size 'this->getNumberOfCells()'.
6280  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6281  */
6282 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
6283 {
6284   int ncell=getNumberOfCells();
6285   std::vector<bool> ret(ncell);
6286   const int *cI=getNodalConnectivityIndex()->begin();
6287   const int *c=getNodalConnectivity()->begin();
6288   for(int i=0;i<ncell;i++)
6289     {
6290       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6291       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6292       ret[i]=cm.isQuadratic();
6293     }
6294   return ret;
6295 }
6296
6297 /*!
6298  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6299  */
6300 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6301 {
6302   if(other->getType()!=UNSTRUCTURED)
6303     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6304   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6305   return MergeUMeshes(this,otherC);
6306 }
6307
6308 /*!
6309  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6310  * computed by averaging coordinates of cell nodes, so this method is not a right
6311  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6312  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6313  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6314  *          components. The caller is to delete this array using decrRef() as it is
6315  *          no more needed.
6316  *  \throw If the coordinates array is not set.
6317  *  \throw If the nodal connectivity of cells is not defined.
6318  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6319  */
6320 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
6321 {
6322   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6323   int spaceDim=getSpaceDimension();
6324   int nbOfCells=getNumberOfCells();
6325   ret->alloc(nbOfCells,spaceDim);
6326   ret->copyStringInfoFrom(*getCoords());
6327   double *ptToFill=ret->getPointer();
6328   const int *nodal=_nodal_connec->begin();
6329   const int *nodalI=_nodal_connec_index->begin();
6330   const double *coor=_coords->begin();
6331   for(int i=0;i<nbOfCells;i++)
6332     {
6333       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6334       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6335       ptToFill+=spaceDim;
6336     }
6337   return ret.retn();
6338 }
6339
6340 /*!
6341  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6342  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
6343  * 
6344  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6345  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6346  * 
6347  * \sa MEDCouplingUMesh::computeCellCenterOfMass
6348  * \throw If \a this is not fully defined (coordinates and connectivity)
6349  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6350  */
6351 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
6352 {
6353   checkFullyDefined();
6354   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6355   int spaceDim=getSpaceDimension();
6356   int nbOfCells=getNumberOfCells();
6357   int nbOfNodes=getNumberOfNodes();
6358   ret->alloc(nbOfCells,spaceDim);
6359   double *ptToFill=ret->getPointer();
6360   const int *nodal=_nodal_connec->begin();
6361   const int *nodalI=_nodal_connec_index->begin();
6362   const double *coor=_coords->begin();
6363   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6364     {
6365       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6366       std::fill(ptToFill,ptToFill+spaceDim,0.);
6367       if(type!=INTERP_KERNEL::NORM_POLYHED)
6368         {
6369           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6370             {
6371               if(*conn>=0 && *conn<nbOfNodes)
6372                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6373               else
6374                 {
6375                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
6376                   throw INTERP_KERNEL::Exception(oss.str());
6377                 }
6378             }
6379           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
6380           if(nbOfNodesInCell>0)
6381             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6382           else
6383             {
6384               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
6385               throw INTERP_KERNEL::Exception(oss.str());
6386             }
6387         }
6388       else
6389         {
6390           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
6391           s.erase(-1);
6392           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
6393             {
6394               if(*it>=0 && *it<nbOfNodes)
6395                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
6396               else
6397                 {
6398                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
6399                   throw INTERP_KERNEL::Exception(oss.str());
6400                 }
6401             }
6402           if(!s.empty())
6403             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
6404           else
6405             {
6406               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
6407               throw INTERP_KERNEL::Exception(oss.str());
6408             }
6409         }
6410     }
6411   return ret.retn();
6412 }
6413
6414 /*!
6415  * Returns a new DataArrayDouble holding barycenters of specified cells. The
6416  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
6417  * are specified via an array of cell ids. 
6418  *  \warning Validity of the specified cell ids is not checked! 
6419  *           Valid range is [ 0, \a this->getNumberOfCells() ).
6420  *  \param [in] begin - an array of cell ids of interest.
6421  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
6422  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
6423  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
6424  *          caller is to delete this array using decrRef() as it is no more needed. 
6425  *  \throw If the coordinates array is not set.
6426  *  \throw If the nodal connectivity of cells is not defined.
6427  *
6428  *  \if ENABLE_EXAMPLES
6429  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
6430  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
6431  *  \endif
6432  */
6433 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6434 {
6435   DataArrayDouble *ret=DataArrayDouble::New();
6436   int spaceDim=getSpaceDimension();
6437   int nbOfTuple=(int)std::distance(begin,end);
6438   ret->alloc(nbOfTuple,spaceDim);
6439   double *ptToFill=ret->getPointer();
6440   double *tmp=new double[spaceDim];
6441   const int *nodal=_nodal_connec->begin();
6442   const int *nodalI=_nodal_connec_index->begin();
6443   const double *coor=_coords->begin();
6444   for(const int *w=begin;w!=end;w++)
6445     {
6446       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6447       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6448       ptToFill+=spaceDim;
6449     }
6450   delete [] tmp;
6451   return ret;
6452 }
6453
6454 /*!
6455  * 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".
6456  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
6457  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
6458  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
6459  * This method is useful to detect 2D cells in 3D space that are not coplanar.
6460  * 
6461  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
6462  * \throw If spaceDim!=3 or meshDim!=2.
6463  * \throw If connectivity of \a this is invalid.
6464  * \throw If connectivity of a cell in \a this points to an invalid node.
6465  */
6466 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
6467 {
6468   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
6469   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6470   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
6471     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
6472   ret->alloc(nbOfCells,4);
6473   double *retPtr(ret->getPointer());
6474   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
6475   const double *coor(_coords->begin());
6476   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
6477     {
6478       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
6479       if(nodalI[1]-nodalI[0]>=4)
6480         {
6481           double aa[3]={coor[nodal[nodalI[0]+1+1]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6482                         coor[nodal[nodalI[0]+1+1]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6483                         coor[nodal[nodalI[0]+1+1]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]}
6484           ,bb[3]={coor[nodal[nodalI[0]+1+2]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6485                         coor[nodal[nodalI[0]+1+2]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6486                         coor[nodal[nodalI[0]+1+2]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]};
6487           double cc[3]={aa[1]*bb[2]-aa[2]*bb[1],aa[2]*bb[0]-aa[0]*bb[2],aa[0]*bb[1]-aa[1]*bb[0]};
6488           for(int j=0;j<3;j++)
6489             {
6490               int nodeId(nodal[nodalI[0]+1+j]);
6491               if(nodeId>=0 && nodeId<nbOfNodes)
6492                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
6493               else
6494                 {
6495                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
6496                   throw INTERP_KERNEL::Exception(oss.str());
6497                 }
6498             }
6499           if(sqrt(cc[0]*cc[0]+cc[1]*cc[1]+cc[2]*cc[2])>1e-7)
6500             {
6501               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6502               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6503             }
6504           else
6505             {
6506               if(nodalI[1]-nodalI[0]==4)
6507                 {
6508                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : cell" << i << " : Presence of The 3 colinear points !";
6509                   throw INTERP_KERNEL::Exception(oss.str());
6510                 }
6511               //
6512               double dd[3]={0.,0.,0.};
6513               for(int offset=nodalI[0]+1;offset<nodalI[1];offset++)
6514                 std::transform(coor+3*nodal[offset],coor+3*(nodal[offset]+1),dd,dd,std::plus<double>());
6515               int nbOfNodesInCell(nodalI[1]-nodalI[0]-1);
6516               std::transform(dd,dd+3,dd,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6517               std::copy(dd,dd+3,matrix+4*2);
6518               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6519               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6520             }
6521         }
6522       else
6523         {
6524           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
6525           throw INTERP_KERNEL::Exception(oss.str());
6526         }
6527     }
6528   return ret.retn();
6529 }
6530
6531 /*!
6532  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6533  * 
6534  */
6535 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
6536 {
6537   if(!da)
6538     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6539   da->checkAllocated();
6540   std::string name(da->getName());
6541   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(name,0));
6542   if(name.empty())
6543     ret->setName("Mesh");
6544   ret->setCoords(da);
6545   int nbOfTuples(da->getNumberOfTuples());
6546   MCAuto<DataArrayInt> c(DataArrayInt::New()),cI(DataArrayInt::New());
6547   c->alloc(2*nbOfTuples,1);
6548   cI->alloc(nbOfTuples+1,1);
6549   int *cp(c->getPointer()),*cip(cI->getPointer());
6550   *cip++=0;
6551   for(int i=0;i<nbOfTuples;i++)
6552     {
6553       *cp++=INTERP_KERNEL::NORM_POINT1;
6554       *cp++=i;
6555       *cip++=2*(i+1);
6556     }
6557   ret->setConnectivity(c,cI,true);
6558   return ret.retn();
6559 }
6560
6561 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::Build1DMeshFromCoords(DataArrayDouble *da)
6562 {
6563   if(!da)
6564     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build01MeshFromCoords : instance of DataArrayDouble must be not null !");
6565   da->checkAllocated();
6566   std::string name(da->getName());
6567   MCAuto<MEDCouplingUMesh> ret;
6568   {
6569     MCAuto<MEDCouplingCMesh> tmp(MEDCouplingCMesh::New());
6570     MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6571     arr->alloc(da->getNumberOfTuples());
6572     tmp->setCoordsAt(0,arr);
6573     ret=tmp->buildUnstructured();
6574   }
6575   ret->setCoords(da);
6576   if(name.empty())
6577     ret->setName("Mesh");
6578   else
6579     ret->setName(name);
6580   return ret;
6581 }
6582
6583 /*!
6584  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
6585  * Cells and nodes of
6586  * the first mesh precede cells and nodes of the second mesh within the result mesh.
6587  *  \param [in] mesh1 - the first mesh.
6588  *  \param [in] mesh2 - the second mesh.
6589  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6590  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6591  *          is no more needed.
6592  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6593  *  \throw If the coordinates array is not set in none of the meshes.
6594  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6595  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6596  */
6597 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6598 {
6599   std::vector<const MEDCouplingUMesh *> tmp(2);
6600   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6601   return MergeUMeshes(tmp);
6602 }
6603
6604 /*!
6605  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
6606  * Cells and nodes of
6607  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
6608  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
6609  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6610  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6611  *          is no more needed.
6612  *  \throw If \a a.size() == 0.
6613  *  \throw If \a a[ *i* ] == NULL.
6614  *  \throw If the coordinates array is not set in none of the meshes.
6615  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6616  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6617  */
6618 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const std::vector<const MEDCouplingUMesh *>& a)
6619 {
6620   std::size_t sz=a.size();
6621   if(sz==0)
6622     return MergeUMeshesLL(a);
6623   for(std::size_t ii=0;ii<sz;ii++)
6624     if(!a[ii])
6625       {
6626         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6627         throw INTERP_KERNEL::Exception(oss.str());
6628       }
6629   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
6630   std::vector< const MEDCouplingUMesh * > aa(sz);
6631   int spaceDim=-3;
6632   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6633     {
6634       const MEDCouplingUMesh *cur=a[i];
6635       const DataArrayDouble *coo=cur->getCoords();
6636       if(coo)
6637         spaceDim=coo->getNumberOfComponents();
6638     }
6639   if(spaceDim==-3)
6640     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6641   for(std::size_t i=0;i<sz;i++)
6642     {
6643       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6644       aa[i]=bb[i];
6645     }
6646   return MergeUMeshesLL(aa);
6647 }
6648
6649 /*!
6650  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
6651  * dimension and sharing the node coordinates array.
6652  * All cells of the first mesh precede all cells of the second mesh
6653  * within the result mesh.
6654  *  \param [in] mesh1 - the first mesh.
6655  *  \param [in] mesh2 - the second mesh.
6656  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6657  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6658  *          is no more needed.
6659  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6660  *  \throw If the meshes do not share the node coordinates array.
6661  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6662  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6663  */
6664 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6665 {
6666   std::vector<const MEDCouplingUMesh *> tmp(2);
6667   tmp[0]=mesh1; tmp[1]=mesh2;
6668   return MergeUMeshesOnSameCoords(tmp);
6669 }
6670
6671 /*!
6672  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6673  * dimension and sharing the node coordinates array.
6674  * All cells of the *i*-th mesh precede all cells of the
6675  * (*i*+1)-th mesh within the result mesh.
6676  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6677  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6678  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6679  *          is no more needed.
6680  *  \throw If \a a.size() == 0.
6681  *  \throw If \a a[ *i* ] == NULL.
6682  *  \throw If the meshes do not share the node coordinates array.
6683  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6684  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6685  */
6686 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6687 {
6688   if(meshes.empty())
6689     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6690   for(std::size_t ii=0;ii<meshes.size();ii++)
6691     if(!meshes[ii])
6692       {
6693         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6694         throw INTERP_KERNEL::Exception(oss.str());
6695       }
6696   const DataArrayDouble *coords=meshes.front()->getCoords();
6697   int meshDim=meshes.front()->getMeshDimension();
6698   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6699   int meshLgth=0;
6700   int meshIndexLgth=0;
6701   for(;iter!=meshes.end();iter++)
6702     {
6703       if(coords!=(*iter)->getCoords())
6704         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6705       if(meshDim!=(*iter)->getMeshDimension())
6706         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6707       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
6708       meshIndexLgth+=(*iter)->getNumberOfCells();
6709     }
6710   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
6711   nodal->alloc(meshLgth,1);
6712   int *nodalPtr=nodal->getPointer();
6713   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
6714   nodalIndex->alloc(meshIndexLgth+1,1);
6715   int *nodalIndexPtr=nodalIndex->getPointer();
6716   int offset=0;
6717   for(iter=meshes.begin();iter!=meshes.end();iter++)
6718     {
6719       const int *nod=(*iter)->getNodalConnectivity()->begin();
6720       const int *index=(*iter)->getNodalConnectivityIndex()->begin();
6721       int nbOfCells=(*iter)->getNumberOfCells();
6722       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
6723       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6724       if(iter!=meshes.begin())
6725         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6726       else
6727         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6728       offset+=meshLgth2;
6729     }
6730   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6731   ret->setName("merge");
6732   ret->setMeshDimension(meshDim);
6733   ret->setConnectivity(nodal,nodalIndex,true);
6734   ret->setCoords(coords);
6735   return ret;
6736 }
6737
6738 /*!
6739  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6740  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
6741  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
6742  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
6743  * New" mode are returned for each input mesh.
6744  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6745  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
6746  *          valid values [0,1,2], see zipConnectivityTraducer().
6747  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
6748  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
6749  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
6750  *          no more needed.
6751  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6752  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6753  *          is no more needed.
6754  *  \throw If \a meshes.size() == 0.
6755  *  \throw If \a meshes[ *i* ] == NULL.
6756  *  \throw If the meshes do not share the node coordinates array.
6757  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
6758  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
6759  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
6760  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
6761  */
6762 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6763 {
6764   //All checks are delegated to MergeUMeshesOnSameCoords
6765   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6766   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6767   corr.resize(meshes.size());
6768   std::size_t nbOfMeshes=meshes.size();
6769   int offset=0;
6770   const int *o2nPtr=o2n->begin();
6771   for(std::size_t i=0;i<nbOfMeshes;i++)
6772     {
6773       DataArrayInt *tmp=DataArrayInt::New();
6774       int curNbOfCells=meshes[i]->getNumberOfCells();
6775       tmp->alloc(curNbOfCells,1);
6776       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6777       offset+=curNbOfCells;
6778       tmp->setName(meshes[i]->getName());
6779       corr[i]=tmp;
6780     }
6781   return ret.retn();
6782 }
6783
6784 /*!
6785  * Makes all given meshes share the nodal connectivity array. The common connectivity
6786  * array is created by concatenating the connectivity arrays of all given meshes. All
6787  * the given meshes must be of the same space dimension but dimension of cells **can
6788  * differ**. This method is particulary useful in MEDLoader context to build a \ref
6789  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6790  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
6791  *  \param [in,out] meshes - a vector of meshes to update.
6792  *  \throw If any of \a meshes is NULL.
6793  *  \throw If the coordinates array is not set in any of \a meshes.
6794  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6795  *  \throw If \a meshes are of different space dimension.
6796  */
6797 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
6798 {
6799   std::size_t sz=meshes.size();
6800   if(sz==0 || sz==1)
6801     return;
6802   std::vector< const DataArrayDouble * > coords(meshes.size());
6803   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6804   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6805     {
6806       if((*it))
6807         {
6808           (*it)->checkConnectivityFullyDefined();
6809           const DataArrayDouble *coo=(*it)->getCoords();
6810           if(coo)
6811             *it2=coo;
6812           else
6813             {
6814               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6815               oss << " has no coordinate array defined !";
6816               throw INTERP_KERNEL::Exception(oss.str());
6817             }
6818         }
6819       else
6820         {
6821           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6822           oss << " is null !";
6823           throw INTERP_KERNEL::Exception(oss.str());
6824         }
6825     }
6826   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6827   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6828   int offset=(*it)->getNumberOfNodes();
6829   (*it++)->setCoords(res);
6830   for(;it!=meshes.end();it++)
6831     {
6832       int oldNumberOfNodes=(*it)->getNumberOfNodes();
6833       (*it)->setCoords(res);
6834       (*it)->shiftNodeNumbersInConn(offset);
6835       offset+=oldNumberOfNodes;
6836     }
6837 }
6838
6839 /*!
6840  * Merges nodes coincident with a given precision within all given meshes that share
6841  * the nodal connectivity array. The given meshes **can be of different** mesh
6842  * dimension. This method is particulary useful in MEDLoader context to build a \ref
6843  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6844  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
6845  *  \param [in,out] meshes - a vector of meshes to update.
6846  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
6847  *  \throw If any of \a meshes is NULL.
6848  *  \throw If the \a meshes do not share the same node coordinates array.
6849  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6850  */
6851 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
6852 {
6853   if(meshes.empty())
6854     return ;
6855   std::set<const DataArrayDouble *> s;
6856   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6857     {
6858       if(*it)
6859         s.insert((*it)->getCoords());
6860       else
6861         {
6862           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 !";
6863           throw INTERP_KERNEL::Exception(oss.str());
6864         }
6865     }
6866   if(s.size()!=1)
6867     {
6868       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 !";
6869       throw INTERP_KERNEL::Exception(oss.str());
6870     }
6871   const DataArrayDouble *coo=*(s.begin());
6872   if(!coo)
6873     return;
6874   //
6875   DataArrayInt *comm,*commI;
6876   coo->findCommonTuples(eps,-1,comm,commI);
6877   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
6878   int oldNbOfNodes=coo->getNumberOfTuples();
6879   int newNbOfNodes;
6880   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6881   if(oldNbOfNodes==newNbOfNodes)
6882     return ;
6883   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->begin(),newNbOfNodes);
6884   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6885     {
6886       (*it)->renumberNodesInConn(o2n->begin());
6887       (*it)->setCoords(newCoords);
6888     } 
6889 }
6890
6891
6892 /*!
6893  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
6894  */
6895 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6896 {
6897   std::size_t i, ip1;
6898   double v[3]={0.,0.,0.};
6899   std::size_t sz=std::distance(begin,end);
6900   if(isQuadratic)
6901     sz/=2;
6902   for(i=0;i<sz;i++)
6903     {
6904       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];
6905       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6906       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6907     }
6908   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6909
6910   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
6911   // SEG3 forming a circle):
6912   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
6913     {
6914       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
6915       for(std::size_t j=0;j<sz;j++)
6916         {
6917           if (j%2)  // current point i is quadratic, next point i+1 is standard
6918             {
6919               i = sz+j;
6920               ip1 = (j+1)%sz; // ip1 = "i+1"
6921             }
6922           else      // current point i is standard, next point i+1 is quadratic
6923             {
6924               i = j;
6925               ip1 = j+sz;
6926             }
6927           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
6928           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
6929           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
6930         }
6931       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6932     }
6933   return (ret>0.);
6934 }
6935
6936 /*!
6937  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
6938  */
6939 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6940 {
6941   std::vector<std::pair<int,int> > edges;
6942   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6943   const int *bgFace=begin;
6944   for(std::size_t i=0;i<nbOfFaces;i++)
6945     {
6946       const int *endFace=std::find(bgFace+1,end,-1);
6947       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6948       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6949         {
6950           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6951           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6952             return false;
6953           edges.push_back(p1);
6954         }
6955       bgFace=endFace+1;
6956     }
6957   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6958 }
6959
6960 /*!
6961  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
6962  */
6963 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
6964 {
6965   double vec0[3],vec1[3];
6966   std::size_t sz=std::distance(begin,end);
6967   if(sz%2!=0)
6968     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
6969   int nbOfNodes=(int)sz/2;
6970   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
6971   const double *pt0=coords+3*begin[0];
6972   const double *pt1=coords+3*begin[nbOfNodes];
6973   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
6974   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
6975 }
6976
6977 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
6978 {
6979   std::size_t sz=std::distance(begin,end);
6980   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
6981   std::size_t nbOfNodes(sz/2);
6982   std::copy(begin,end,(int *)tmp);
6983   for(std::size_t j=1;j<nbOfNodes;j++)
6984     {
6985       begin[j]=tmp[nbOfNodes-j];
6986       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
6987     }
6988 }
6989
6990 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
6991 {
6992   std::size_t sz=std::distance(begin,end);
6993   if(sz!=4)
6994     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
6995   double vec0[3],vec1[3];
6996   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
6997   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]; 
6998   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;
6999 }
7000
7001 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7002 {
7003   std::size_t sz=std::distance(begin,end);
7004   if(sz!=5)
7005     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
7006   double vec0[3];
7007   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7008   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7009   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7010 }
7011
7012 /*!
7013  * 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 ) 
7014  * 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
7015  * a 2D space.
7016  *
7017  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7018  * \param [in] coords the coordinates with nb of components exactly equal to 3
7019  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7020  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7021  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7022  */
7023 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
7024 {
7025   int nbFaces=std::count(begin+1,end,-1)+1;
7026   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7027   double *vPtr=v->getPointer();
7028   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7029   double *pPtr=p->getPointer();
7030   const int *stFaceConn=begin+1;
7031   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7032     {
7033       const int *endFaceConn=std::find(stFaceConn,end,-1);
7034       ComputeVecAndPtOfFace(eps,coords->begin(),stFaceConn,endFaceConn,vPtr,pPtr);
7035       stFaceConn=endFaceConn+1;
7036     }
7037   pPtr=p->getPointer(); vPtr=v->getPointer();
7038   DataArrayInt *comm1=0,*commI1=0;
7039   v->findCommonTuples(eps,-1,comm1,commI1);
7040   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7041   const int *comm1Ptr=comm1->begin();
7042   const int *commI1Ptr=commI1->begin();
7043   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7044   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7045   //
7046   MCAuto<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7047   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7048   mm->finishInsertingCells();
7049   //
7050   for(int i=0;i<nbOfGrps1;i++)
7051     {
7052       int vecId=comm1Ptr[commI1Ptr[i]];
7053       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7054       DataArrayInt *comm2=0,*commI2=0;
7055       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7056       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7057       const int *comm2Ptr=comm2->begin();
7058       const int *commI2Ptr=commI2->begin();
7059       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7060       for(int j=0;j<nbOfGrps2;j++)
7061         {
7062           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7063             {
7064               res->insertAtTheEnd(begin,end);
7065               res->pushBackSilent(-1);
7066             }
7067           else
7068             {
7069               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7070               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
7071               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7072               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7073               MCAuto<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7074               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7075               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7076               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7077               const int *idsNodePtr=idsNode->begin();
7078               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];
7079               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7080               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7081               if(std::abs(norm)>eps)
7082                 {
7083                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7084                   mm3->rotate(center,vec,angle);
7085                 }
7086               mm3->changeSpaceDimension(2);
7087               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7088               const int *conn4=mm4->getNodalConnectivity()->begin();
7089               const int *connI4=mm4->getNodalConnectivityIndex()->begin();
7090               int nbOfCells=mm4->getNumberOfCells();
7091               for(int k=0;k<nbOfCells;k++)
7092                 {
7093                   int l=0;
7094                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7095                     res->pushBackSilent(idsNodePtr[*work]);
7096                   res->pushBackSilent(-1);
7097                 }
7098             }
7099         }
7100     }
7101   res->popBackSilent();
7102 }
7103
7104 /*!
7105  * 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
7106  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7107  * 
7108  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7109  * \param [in] coords coordinates expected to have 3 components.
7110  * \param [in] begin start of the nodal connectivity of the face.
7111  * \param [in] end end of the nodal connectivity (excluded) of the face.
7112  * \param [out] v the normalized vector of size 3
7113  * \param [out] p the pos of plane
7114  */
7115 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
7116 {
7117   std::size_t nbPoints=std::distance(begin,end);
7118   if(nbPoints<3)
7119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7120   double vec[3]={0.,0.,0.};
7121   std::size_t j=0;
7122   bool refFound=false;
7123   for(;j<nbPoints-1 && !refFound;j++)
7124     {
7125       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7126       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7127       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7128       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7129       if(norm>eps)
7130         {
7131           refFound=true;
7132           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7133         }
7134     }
7135   for(std::size_t i=j;i<nbPoints-1;i++)
7136     {
7137       double curVec[3];
7138       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7139       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7140       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7141       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7142       if(norm<eps)
7143         continue;
7144       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7145       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];
7146       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7147       if(norm>eps)
7148         {
7149           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7150           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7151           return ;
7152         }
7153     }
7154   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7155 }
7156
7157 /*!
7158  * This method tries to obtain a well oriented polyhedron.
7159  * If the algorithm fails, an exception will be thrown.
7160  */
7161 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
7162 {
7163   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7164   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7165   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7166   isPerm[0]=true;
7167   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7168   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7169   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7170   //
7171   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7172     {
7173       bgFace=begin;
7174       std::size_t smthChanged=0;
7175       for(std::size_t i=0;i<nbOfFaces;i++)
7176         {
7177           endFace=std::find(bgFace+1,end,-1);
7178           nbOfEdgesInFace=std::distance(bgFace,endFace);
7179           if(!isPerm[i])
7180             {
7181               bool b;
7182               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7183                 {
7184                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7185                   std::pair<int,int> p2(p1.second,p1.first);
7186                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7187                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7188                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7189                 }
7190               if(isPerm[i])
7191                 { 
7192                   if(!b)
7193                     std::reverse(bgFace+1,endFace);
7194                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7195                     {
7196                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7197                       std::pair<int,int> p2(p1.second,p1.first);
7198                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7199                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7200                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7201                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7202                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7203                       if(it!=edgesOK.end())
7204                         {
7205                           edgesOK.erase(it);
7206                           edgesFinished.push_back(p1);
7207                         }
7208                       else
7209                         edgesOK.push_back(p1);
7210                     }
7211                 }
7212             }
7213           bgFace=endFace+1;
7214         }
7215       if(smthChanged==0)
7216         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7217     }
7218   if(!edgesOK.empty())
7219     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7220   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7221     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7222       bgFace=begin;
7223       for(std::size_t i=0;i<nbOfFaces;i++)
7224         {
7225           endFace=std::find(bgFace+1,end,-1);
7226           std::reverse(bgFace+1,endFace);
7227           bgFace=endFace+1;
7228         }
7229     }
7230 }
7231
7232
7233 /*!
7234  * This method makes the assumption spacedimension == meshdimension == 2.
7235  * This method works only for linear cells.
7236  * 
7237  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7238  */
7239 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
7240 {
7241   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7242     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7243   MCAuto<MEDCouplingUMesh> skin(computeSkin());
7244   int oldNbOfNodes(skin->getNumberOfNodes());
7245   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
7246   int nbOfNodesExpected(skin->getNumberOfNodes());
7247   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
7248   int nbCells(skin->getNumberOfCells());
7249   if(nbCells==nbOfNodesExpected)
7250     return buildUnionOf2DMeshLinear(skin,n2o);
7251   else if(2*nbCells==nbOfNodesExpected)
7252     return buildUnionOf2DMeshQuadratic(skin,n2o);
7253   else
7254     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
7255 }
7256
7257 /*!
7258  * This method makes the assumption spacedimension == meshdimension == 3.
7259  * This method works only for linear cells.
7260  * 
7261  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7262  */
7263 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
7264 {
7265   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7266     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7267   MCAuto<MEDCouplingUMesh> m=computeSkin();
7268   const int *conn=m->getNodalConnectivity()->begin();
7269   const int *connI=m->getNodalConnectivityIndex()->begin();
7270   int nbOfCells=m->getNumberOfCells();
7271   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7272   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7273   if(nbOfCells<1)
7274     return ret.retn();
7275   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7276   for(int i=1;i<nbOfCells;i++)
7277     {
7278       *work++=-1;
7279       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7280     }
7281   return ret.retn();
7282 }
7283
7284 /*!
7285  * \brief Creates a graph of cell neighbors
7286  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
7287  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
7288  *  For example
7289  *  - index:  0 3 5 6 6
7290  *  - value:  1 2 3 2 3 3
7291  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7292  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
7293  */
7294 MEDCouplingSkyLineArray* MEDCouplingUMesh::generateGraph() const
7295 {
7296   checkConnectivityFullyDefined();
7297
7298   int meshDim = this->getMeshDimension();
7299   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
7300   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
7301   this->getReverseNodalConnectivity(revConn,indexr);
7302   const int* indexr_ptr=indexr->begin();
7303   const int* revConn_ptr=revConn->begin();
7304
7305   const MEDCoupling::DataArrayInt* index;
7306   const MEDCoupling::DataArrayInt* conn;
7307   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
7308   index=this->getNodalConnectivityIndex();
7309   int nbCells=this->getNumberOfCells();
7310   const int* index_ptr=index->begin();
7311   const int* conn_ptr=conn->begin();
7312
7313   //creating graph arcs (cell to cell relations)
7314   //arcs are stored in terms of (index,value) notation
7315   // 0 3 5 6 6
7316   // 1 2 3 2 3 3
7317   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7318   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
7319
7320   //warning here one node have less than or equal effective number of cell with it
7321   //but cell could have more than effective nodes
7322   //because other equals nodes in other domain (with other global inode)
7323   std::vector <int> cell2cell_index(nbCells+1,0);
7324   std::vector <int> cell2cell;
7325   cell2cell.reserve(3*nbCells);
7326
7327   for (int icell=0; icell<nbCells;icell++)
7328     {
7329       std::map<int,int > counter;
7330       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
7331         {
7332           int inode=conn_ptr[iconn];
7333           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
7334             {
7335               int icell2=revConn_ptr[iconnr];
7336               std::map<int,int>::iterator iter=counter.find(icell2);
7337               if (iter!=counter.end()) (iter->second)++;
7338               else counter.insert(std::make_pair(icell2,1));
7339             }
7340         }
7341       for (std::map<int,int>::const_iterator iter=counter.begin();
7342            iter!=counter.end(); iter++)
7343         if (iter->second >= meshDim)
7344           {
7345             cell2cell_index[icell+1]++;
7346             cell2cell.push_back(iter->first);
7347           }
7348     }
7349   indexr->decrRef();
7350   revConn->decrRef();
7351   cell2cell_index[0]=0;
7352   for (int icell=0; icell<nbCells;icell++)
7353     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
7354
7355   //filling up index and value to create skylinearray structure
7356   MEDCouplingSkyLineArray * array(MEDCouplingSkyLineArray::New(cell2cell_index,cell2cell));
7357   return array;
7358 }
7359
7360
7361 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
7362 {
7363   int nbOfCells=getNumberOfCells();
7364   if(nbOfCells<=0)
7365     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7366   ofs << "  <" << getVTKDataSetType() << ">\n";
7367   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7368   ofs << "      <PointData>\n" << pointData << std::endl;
7369   ofs << "      </PointData>\n";
7370   ofs << "      <CellData>\n" << cellData << std::endl;
7371   ofs << "      </CellData>\n";
7372   ofs << "      <Points>\n";
7373   if(getSpaceDimension()==3)
7374     _coords->writeVTK(ofs,8,"Points",byteData);
7375   else
7376     {
7377       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7378       coo->writeVTK(ofs,8,"Points",byteData);
7379     }
7380   ofs << "      </Points>\n";
7381   ofs << "      <Cells>\n";
7382   const int *cPtr=_nodal_connec->begin();
7383   const int *cIPtr=_nodal_connec_index->begin();
7384   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7385   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7386   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7387   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7388   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7389   int szFaceOffsets=0,szConn=0;
7390   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7391     {
7392       *w2=cPtr[cIPtr[i]];
7393       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7394         {
7395           *w1=-1;
7396           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7397           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7398         }
7399       else
7400         {
7401           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7402           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7403           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7404           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7405           w4=std::copy(c.begin(),c.end(),w4);
7406         }
7407     }
7408   types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
7409   types->writeVTK(ofs,8,"UInt8","types",byteData);
7410   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
7411   if(szFaceOffsets!=0)
7412     {//presence of Polyhedra
7413       connectivity->reAlloc(szConn);
7414       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
7415       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7416       w1=faces->getPointer();
7417       for(int i=0;i<nbOfCells;i++)
7418         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7419           {
7420             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7421             *w1++=nbFaces;
7422             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7423             for(int j=0;j<nbFaces;j++)
7424               {
7425                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7426                 *w1++=(int)std::distance(w6,w5);
7427                 w1=std::copy(w6,w5,w1);
7428                 w6=w5+1;
7429               }
7430           }
7431       faces->writeVTK(ofs,8,"Int32","faces",byteData);
7432     }
7433   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
7434   ofs << "      </Cells>\n";
7435   ofs << "    </Piece>\n";
7436   ofs << "  </" << getVTKDataSetType() << ">\n";
7437 }
7438
7439 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
7440 {
7441   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
7442   if(_mesh_dim==-2)
7443     { stream << " Not set !"; return ; }
7444   stream << " Mesh dimension : " << _mesh_dim << ".";
7445   if(_mesh_dim==-1)
7446     return ;
7447   if(!_coords)
7448     { stream << " No coordinates set !"; return ; }
7449   if(!_coords->isAllocated())
7450     { stream << " Coordinates set but not allocated !"; return ; }
7451   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
7452   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
7453   if(!_nodal_connec_index)
7454     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
7455   if(!_nodal_connec_index->isAllocated())
7456     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
7457   int lgth=_nodal_connec_index->getNumberOfTuples();
7458   int cpt=_nodal_connec_index->getNumberOfComponents();
7459   if(cpt!=1 || lgth<1)
7460     return ;
7461   stream << std::endl << "Number of cells : " << lgth-1 << ".";
7462 }
7463
7464 std::string MEDCouplingUMesh::getVTKDataSetType() const
7465 {
7466   return std::string("UnstructuredGrid");
7467 }
7468
7469 std::string MEDCouplingUMesh::getVTKFileExtension() const
7470 {
7471   return std::string("vtu");
7472 }
7473
7474
7475
7476 /**
7477  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
7478  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
7479  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
7480  * The caller is to deal with the resulting DataArrayInt.
7481  *  \throw If the coordinate array is not set.
7482  *  \throw If the nodal connectivity of the cells is not defined.
7483  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
7484  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
7485  *
7486  * \sa DataArrayInt::sortEachPairToMakeALinkedList
7487  */
7488 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
7489 {
7490   checkFullyDefined();
7491   if(getMeshDimension()!=1)
7492     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
7493
7494   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
7495   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
7496   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
7497   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
7498   const int *d(_d->begin()), *dI(_dI->begin());
7499   const int *rD(_rD->begin()), *rDI(_rDI->begin());
7500   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
7501   const int * dsi(_dsi->begin());
7502   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
7503   m_points=0;
7504   if (dsii->getNumberOfTuples())
7505     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
7506
7507   int nc(getNumberOfCells());
7508   MCAuto<DataArrayInt> result(DataArrayInt::New());
7509   result->alloc(nc,1);
7510
7511   // set of edges not used so far
7512   std::set<int> edgeSet;
7513   for (int i=0; i<nc; edgeSet.insert(i), i++);
7514
7515   int startSeg=0;
7516   int newIdx=0;
7517   // while we have points with only one neighbor segments
7518   do
7519     {
7520       std::list<int> linePiece;
7521       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
7522       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
7523         {
7524           // Fill the list forward (resp. backward) from the start segment:
7525           int activeSeg = startSeg;
7526           int prevPointId = -20;
7527           int ptId;
7528           while (!edgeSet.empty())
7529             {
7530               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
7531                 {
7532                   if (direction==0)
7533                     linePiece.push_back(activeSeg);
7534                   else
7535                     linePiece.push_front(activeSeg);
7536                   edgeSet.erase(activeSeg);
7537                 }
7538
7539               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
7540               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
7541               if (dsi[ptId] == 1) // hitting the end of the line
7542                 break;
7543               prevPointId = ptId;
7544               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
7545               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
7546             }
7547         }
7548       // Done, save final piece into DA:
7549       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
7550       newIdx += linePiece.size();
7551
7552       // identify next valid start segment (one which is not consumed)
7553       if(!edgeSet.empty())
7554         startSeg = *(edgeSet.begin());
7555     }
7556   while (!edgeSet.empty());
7557   return result.retn();
7558 }
7559
7560 /**
7561  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
7562  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
7563  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
7564  * a minimal creation of new nodes is wanted.
7565  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
7566  * nodes if a SEG3 is split without information of middle.
7567  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
7568  * avoid to have a non conform mesh.
7569  *
7570  * \return int - the number of new nodes created (in most of cases 0).
7571  * 
7572  * \throw If \a this is not coherent.
7573  * \throw If \a this has not spaceDim equal to 2.
7574  * \throw If \a this has not meshDim equal to 2.
7575  * \throw If some subcells needed to be split are orphan.
7576  * \sa MEDCouplingUMesh::conformize2D
7577  */
7578 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
7579 {
7580   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
7581     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
7582   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
7583   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
7584     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
7585   if(midOpt==0 && midOptI==0)
7586     {
7587       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
7588       return 0;
7589     }
7590   else if(midOpt!=0 && midOptI!=0)
7591     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
7592   else
7593     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
7594 }
7595
7596 /*!
7597  * 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
7598  * 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
7599  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7600  * 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
7601  * 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.
7602  * 
7603  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7604  */
7605 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
7606 {
7607   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7608   if(sz>=4)
7609     {
7610       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7611       if(cm.getDimension()==2)
7612         {
7613           const int *node=nodalConnBg+1;
7614           int startNode=*node++;
7615           double refX=coords[2*startNode];
7616           for(;node!=nodalConnEnd;node++)
7617             {
7618               if(coords[2*(*node)]<refX)
7619                 {
7620                   startNode=*node;
7621                   refX=coords[2*startNode];
7622                 }
7623             }
7624           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7625           refX=1e300;
7626           double tmp1;
7627           double tmp2[2];
7628           double angle0=-M_PI/2;
7629           //
7630           int nextNode=-1;
7631           int prevNode=-1;
7632           double resRef;
7633           double angleNext=0.;
7634           while(nextNode!=startNode)
7635             {
7636               nextNode=-1;
7637               resRef=1e300;
7638               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7639                 {
7640                   if(*node!=tmpOut.back() && *node!=prevNode)
7641                     {
7642                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7643                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7644                       double res;
7645                       if(angleM<=angle0)
7646                         res=angle0-angleM;
7647                       else
7648                         res=angle0-angleM+2.*M_PI;
7649                       if(res<resRef)
7650                         {
7651                           nextNode=*node;
7652                           resRef=res;
7653                           angleNext=angleM;
7654                         }
7655                     }
7656                 }
7657               if(nextNode!=startNode)
7658                 {
7659                   angle0=angleNext-M_PI;
7660                   if(angle0<-M_PI)
7661                     angle0+=2*M_PI;
7662                   prevNode=tmpOut.back();
7663                   tmpOut.push_back(nextNode);
7664                 }
7665             }
7666           std::vector<int> tmp3(2*(sz-1));
7667           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7668           std::copy(nodalConnBg+1,nodalConnEnd,it);
7669           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7670             {
7671               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7672               return false;
7673             }
7674           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7675             {
7676               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7677               return false;
7678             }
7679           else
7680             {
7681               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7682               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7683               return true;
7684             }
7685         }
7686       else
7687         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7688     }
7689   else
7690     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7691 }
7692
7693 /*!
7694  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7695  * 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.
7696  * 
7697  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7698  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7699  * \param [in,out] arr array in which the remove operation will be done.
7700  * \param [in,out] arrIndx array in the remove operation will modify
7701  * \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])
7702  * \return true if \b arr and \b arrIndx have been modified, false if not.
7703  */
7704 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
7705 {
7706   if(!arrIndx || !arr)
7707     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7708   if(offsetForRemoval<0)
7709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7710   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7711   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7712   int *arrIPtr=arrIndx->getPointer();
7713   *arrIPtr++=0;
7714   int previousArrI=0;
7715   const int *arrPtr=arr->begin();
7716   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7717   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7718     {
7719       if(*arrIPtr-previousArrI>offsetForRemoval)
7720         {
7721           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7722             {
7723               if(s.find(*work)==s.end())
7724                 arrOut.push_back(*work);
7725             }
7726         }
7727       previousArrI=*arrIPtr;
7728       *arrIPtr=(int)arrOut.size();
7729     }
7730   if(arr->getNumberOfTuples()==arrOut.size())
7731     return false;
7732   arr->alloc((int)arrOut.size(),1);
7733   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7734   return true;
7735 }
7736
7737 /*!
7738  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7739  * (\ref numbering-indirect).
7740  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7741  * The selection of extraction is done standardly in new2old format.
7742  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7743  *
7744  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7745  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7746  * \param [in] arrIn arr origin array from which the extraction will be done.
7747  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7748  * \param [out] arrOut the resulting array
7749  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7750  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
7751  */
7752 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7753                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7754 {
7755   if(!arrIn || !arrIndxIn)
7756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7757   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7758   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7759     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
7760   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7761   const int *arrInPtr=arrIn->begin();
7762   const int *arrIndxPtr=arrIndxIn->begin();
7763   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7764   if(nbOfGrps<0)
7765     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7766   int maxSizeOfArr=arrIn->getNumberOfTuples();
7767   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7768   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7769   arrIo->alloc((int)(sz+1),1);
7770   const int *idsIt=idsOfSelectBg;
7771   int *work=arrIo->getPointer();
7772   *work++=0;
7773   int lgth=0;
7774   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7775     {
7776       if(*idsIt>=0 && *idsIt<nbOfGrps)
7777         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7778       else
7779         {
7780           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7781           throw INTERP_KERNEL::Exception(oss.str());
7782         }
7783       if(lgth>=work[-1])
7784         *work=lgth;
7785       else
7786         {
7787           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7788           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7789           throw INTERP_KERNEL::Exception(oss.str());
7790         }
7791     }
7792   arro->alloc(lgth,1);
7793   work=arro->getPointer();
7794   idsIt=idsOfSelectBg;
7795   for(std::size_t i=0;i<sz;i++,idsIt++)
7796     {
7797       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7798         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7799       else
7800         {
7801           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7802           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7803           throw INTERP_KERNEL::Exception(oss.str());
7804         }
7805     }
7806   arrOut=arro.retn();
7807   arrIndexOut=arrIo.retn();
7808 }
7809
7810 /*!
7811  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7812  * (\ref numbering-indirect).
7813  * 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 ).
7814  * The selection of extraction is done standardly in new2old format.
7815  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7816  *
7817  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
7818  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
7819  * \param [in] idsOfSelectStep
7820  * \param [in] arrIn arr origin array from which the extraction will be done.
7821  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7822  * \param [out] arrOut the resulting array
7823  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7824  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
7825  */
7826 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7827                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7828 {
7829   if(!arrIn || !arrIndxIn)
7830     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
7831   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7832   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7833     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
7834   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
7835   const int *arrInPtr=arrIn->begin();
7836   const int *arrIndxPtr=arrIndxIn->begin();
7837   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7838   if(nbOfGrps<0)
7839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7840   int maxSizeOfArr=arrIn->getNumberOfTuples();
7841   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7842   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7843   arrIo->alloc((int)(sz+1),1);
7844   int idsIt=idsOfSelectStart;
7845   int *work=arrIo->getPointer();
7846   *work++=0;
7847   int lgth=0;
7848   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
7849     {
7850       if(idsIt>=0 && idsIt<nbOfGrps)
7851         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
7852       else
7853         {
7854           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7855           throw INTERP_KERNEL::Exception(oss.str());
7856         }
7857       if(lgth>=work[-1])
7858         *work=lgth;
7859       else
7860         {
7861           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
7862           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
7863           throw INTERP_KERNEL::Exception(oss.str());
7864         }
7865     }
7866   arro->alloc(lgth,1);
7867   work=arro->getPointer();
7868   idsIt=idsOfSelectStart;
7869   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
7870     {
7871       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
7872         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
7873       else
7874         {
7875           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
7876           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7877           throw INTERP_KERNEL::Exception(oss.str());
7878         }
7879     }
7880   arrOut=arro.retn();
7881   arrIndexOut=arrIo.retn();
7882 }
7883
7884 /*!
7885  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7886  * 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
7887  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7888  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7889  *
7890  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7891  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7892  * \param [in] arrIn arr origin array from which the extraction will be done.
7893  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7894  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
7895  * \param [in] srcArrIndex index array of \b srcArr
7896  * \param [out] arrOut the resulting array
7897  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7898  * 
7899  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7900  */
7901 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7902                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7903                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7904 {
7905   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7906     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7907   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7908   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7909   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7910   std::vector<bool> v(nbOfTuples,true);
7911   int offset=0;
7912   const int *arrIndxInPtr=arrIndxIn->begin();
7913   const int *srcArrIndexPtr=srcArrIndex->begin();
7914   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7915     {
7916       if(*it>=0 && *it<nbOfTuples)
7917         {
7918           v[*it]=false;
7919           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7920         }
7921       else
7922         {
7923           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7924           throw INTERP_KERNEL::Exception(oss.str());
7925         }
7926     }
7927   srcArrIndexPtr=srcArrIndex->begin();
7928   arrIo->alloc(nbOfTuples+1,1);
7929   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7930   const int *arrInPtr=arrIn->begin();
7931   const int *srcArrPtr=srcArr->begin();
7932   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7933   int *arroPtr=arro->getPointer();
7934   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7935     {
7936       if(v[ii])
7937         {
7938           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7939           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7940         }
7941       else
7942         {
7943           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7944           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7945           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7946         }
7947     }
7948   arrOut=arro.retn();
7949   arrIndexOut=arrIo.retn();
7950 }
7951
7952 /*!
7953  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7954  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7955  *
7956  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7957  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7958  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7959  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7960  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
7961  * \param [in] srcArrIndex index array of \b srcArr
7962  * 
7963  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
7964  */
7965 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7966                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
7967 {
7968   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7969     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7970   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7971   const int *arrIndxInPtr=arrIndxIn->begin();
7972   const int *srcArrIndexPtr=srcArrIndex->begin();
7973   int *arrInOutPtr=arrInOut->getPointer();
7974   const int *srcArrPtr=srcArr->begin();
7975   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7976     {
7977       if(*it>=0 && *it<nbOfTuples)
7978         {
7979           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7980             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7981           else
7982             {
7983               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] !";
7984               throw INTERP_KERNEL::Exception(oss.str());
7985             }
7986         }
7987       else
7988         {
7989           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7990           throw INTERP_KERNEL::Exception(oss.str());
7991         }
7992     }
7993 }
7994
7995 /*!
7996  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7997  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7998  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
7999  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8000  * A negative value in \b arrIn means that it is ignored.
8001  * 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.
8002  * 
8003  * \param [in] arrIn arr origin array from which the extraction will be done.
8004  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8005  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8006  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8007  */
8008 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8009 {
8010   int seed=0,nbOfDepthPeelingPerformed=0;
8011   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8012 }
8013
8014 /*!
8015  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8016  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8017  * 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]].
8018  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8019  * A negative value in \b arrIn means that it is ignored.
8020  * 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.
8021  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8022  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8023  * \param [in] arrIn arr origin array from which the extraction will be done.
8024  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8025  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8026  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8027  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8028  * \sa MEDCouplingUMesh::partitionBySpreadZone
8029  */
8030 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
8031 {
8032   nbOfDepthPeelingPerformed=0;
8033   if(!arrIndxIn)
8034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8035   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8036   if(nbOfTuples<=0)
8037     {
8038       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8039       return ret;
8040     }
8041   //
8042   std::vector<bool> fetched(nbOfTuples,false);
8043   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8044 }
8045
8046
8047 /*!
8048  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8049  * 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
8050  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8051  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8052  *
8053  * \param [in] start begin of set of ids of the input extraction (included)
8054  * \param [in] end end of set of ids of the input extraction (excluded)
8055  * \param [in] step step of the set of ids in range mode.
8056  * \param [in] arrIn arr origin array from which the extraction will be done.
8057  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8058  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8059  * \param [in] srcArrIndex index array of \b srcArr
8060  * \param [out] arrOut the resulting array
8061  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8062  * 
8063  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8064  */
8065 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8066                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8067                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
8068 {
8069   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8070     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
8071   MCAuto<DataArrayInt> arro=DataArrayInt::New();
8072   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
8073   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8074   int offset=0;
8075   const int *arrIndxInPtr=arrIndxIn->begin();
8076   const int *srcArrIndexPtr=srcArrIndex->begin();
8077   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
8078   int it=start;
8079   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8080     {
8081       if(it>=0 && it<nbOfTuples)
8082         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8083       else
8084         {
8085           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8086           throw INTERP_KERNEL::Exception(oss.str());
8087         }
8088     }
8089   srcArrIndexPtr=srcArrIndex->begin();
8090   arrIo->alloc(nbOfTuples+1,1);
8091   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8092   const int *arrInPtr=arrIn->begin();
8093   const int *srcArrPtr=srcArr->begin();
8094   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8095   int *arroPtr=arro->getPointer();
8096   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8097     {
8098       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8099       if(pos<0)
8100         {
8101           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8102           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8103         }
8104       else
8105         {
8106           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8107           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8108         }
8109     }
8110   arrOut=arro.retn();
8111   arrIndexOut=arrIo.retn();
8112 }
8113
8114 /*!
8115  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8116  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8117  *
8118  * \param [in] start begin of set of ids of the input extraction (included)
8119  * \param [in] end end of set of ids of the input extraction (excluded)
8120  * \param [in] step step of the set of ids in range mode.
8121  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8122  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8123  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8124  * \param [in] srcArrIndex index array of \b srcArr
8125  * 
8126  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8127  */
8128 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8129                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
8130 {
8131   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8132     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
8133   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8134   const int *arrIndxInPtr=arrIndxIn->begin();
8135   const int *srcArrIndexPtr=srcArrIndex->begin();
8136   int *arrInOutPtr=arrInOut->getPointer();
8137   const int *srcArrPtr=srcArr->begin();
8138   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
8139   int it=start;
8140   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8141     {
8142       if(it>=0 && it<nbOfTuples)
8143         {
8144           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
8145             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
8146           else
8147             {
8148               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8149               throw INTERP_KERNEL::Exception(oss.str());
8150             }
8151         }
8152       else
8153         {
8154           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8155           throw INTERP_KERNEL::Exception(oss.str());
8156         }
8157     }
8158 }
8159
8160 /*!
8161  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8162  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8163  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8164  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8165  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8166  * 
8167  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8168  */
8169 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
8170 {
8171   checkFullyDefined();
8172   int mdim=getMeshDimension();
8173   int spaceDim=getSpaceDimension();
8174   if(mdim!=spaceDim)
8175     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8176   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8177   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8178   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
8179   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8180   ret->setCoords(getCoords());
8181   ret->allocateCells((int)partition.size());
8182   //
8183   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8184     {
8185       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8186       MCAuto<DataArrayInt> cell;
8187       switch(mdim)
8188       {
8189         case 2:
8190           cell=tmp->buildUnionOf2DMesh();
8191           break;
8192         case 3:
8193           cell=tmp->buildUnionOf3DMesh();
8194           break;
8195         default:
8196           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8197       }
8198
8199       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->begin()+1);
8200     }
8201   //
8202   ret->finishInsertingCells();
8203   return ret.retn();
8204 }
8205
8206 /*!
8207  * This method partitions \b this into contiguous zone.
8208  * This method only needs a well defined connectivity. Coordinates are not considered here.
8209  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8210  */
8211 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
8212 {
8213   DataArrayInt *neigh=0,*neighI=0;
8214   computeNeighborsOfCells(neigh,neighI);
8215   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8216   return PartitionBySpreadZone(neighAuto,neighIAuto);
8217 }
8218
8219 std::vector<DataArrayInt *> MEDCouplingUMesh::PartitionBySpreadZone(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8220 {
8221   if(!arrIn || !arrIndxIn)
8222     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : null input pointers !");
8223   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8224   int nbOfTuples(arrIndxIn->getNumberOfTuples());
8225   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1 || nbOfTuples<1)
8226     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : invalid arrays in input !");
8227   int nbOfCellsCur(nbOfTuples-1);
8228   std::vector<DataArrayInt *> ret;
8229   if(nbOfCellsCur<=0)
8230     return ret;
8231   std::vector<bool> fetchedCells(nbOfCellsCur,false);
8232   std::vector< MCAuto<DataArrayInt> > ret2;
8233   int seed=0;
8234   while(seed<nbOfCellsCur)
8235     {
8236       int nbOfPeelPerformed=0;
8237       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfPeelPerformed));
8238       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8239     }
8240   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8241     ret.push_back((*it).retn());
8242   return ret;
8243 }
8244
8245 /*!
8246  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8247  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8248  *
8249  * \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.
8250  * \return a newly allocated DataArrayInt to be managed by the caller.
8251  * \throw In case of \a code has not the right format (typically of size 3*n)
8252  */
8253 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
8254 {
8255   MCAuto<DataArrayInt> ret=DataArrayInt::New();
8256   std::size_t nb=code.size()/3;
8257   if(code.size()%3!=0)
8258     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8259   ret->alloc((int)nb,2);
8260   int *retPtr=ret->getPointer();
8261   for(std::size_t i=0;i<nb;i++,retPtr+=2)
8262     {
8263       retPtr[0]=code[3*i+2];
8264       retPtr[1]=code[3*i+2]+code[3*i+1];
8265     }
8266   return ret.retn();
8267 }
8268
8269 /*!
8270  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
8271  * All cells in \a this are expected to be linear 3D cells.
8272  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
8273  * It leads to an increase to number of cells.
8274  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
8275  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
8276  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
8277  *
8278  * \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.
8279  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
8280  * \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. 
8281  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
8282  *          an id of old cell producing it. The caller is to delete this array using
8283  *         decrRef() as it is no more needed.
8284  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
8285  *
8286  * \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
8287  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
8288  * 
8289  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
8290  * \throw If \a this is not fully constituted with linear 3D cells.
8291  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
8292  */
8293 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
8294 {
8295   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
8296   checkConnectivityFullyDefined();
8297   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8298     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
8299   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
8300   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
8301   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
8302   int *retPt(ret->getPointer());
8303   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
8304   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
8305   const int *oldc(_nodal_connec->begin());
8306   const int *oldci(_nodal_connec_index->begin());
8307   const double *coords(_coords->begin());
8308   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
8309     {
8310       std::vector<int> a; std::vector<double> b;
8311       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
8312       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
8313       const int *aa(&a[0]);
8314       if(!b.empty())
8315         {
8316           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
8317             if(*it<0)
8318               *it=(-(*(it))-1+nbNodes);
8319           addPts->insertAtTheEnd(b.begin(),b.end());
8320           nbNodes+=(int)b.size()/3;
8321         }
8322       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
8323         newConn->insertAtTheEnd(aa,aa+4);
8324     }
8325   if(!addPts->empty())
8326     {
8327       addPts->rearrange(3);
8328       nbOfAdditionalPoints=addPts->getNumberOfTuples();
8329       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
8330       ret0->setCoords(addPts);
8331     }
8332   else
8333     {
8334       nbOfAdditionalPoints=0;
8335       ret0->setCoords(getCoords());
8336     }
8337   ret0->setNodalConnectivity(newConn);
8338   //
8339   ret->computeOffsetsFull();
8340   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
8341   return ret0.retn();
8342 }
8343
8344 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8345     _own_cell(true),_cell_id(-1),_nb_cell(0)
8346 {
8347   if(mesh)
8348     {
8349       mesh->incrRef();
8350       _nb_cell=mesh->getNumberOfCells();
8351     }
8352 }
8353
8354 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8355 {
8356   if(_mesh)
8357     _mesh->decrRef();
8358   if(_own_cell)
8359     delete _cell;
8360 }
8361
8362 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8363     _own_cell(false),_cell_id(bg-1),
8364     _nb_cell(end)
8365 {
8366   if(mesh)
8367     mesh->incrRef();
8368 }
8369
8370 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8371 {
8372   _cell_id++;
8373   if(_cell_id<_nb_cell)
8374     {
8375       _cell->next();
8376       return _cell;
8377     }
8378   else
8379     return 0;
8380 }
8381
8382 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8383 {
8384   if(_mesh)
8385     _mesh->incrRef();
8386 }
8387
8388 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8389 {
8390   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8391 }
8392
8393 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8394 {
8395   if(_mesh)
8396     _mesh->decrRef();
8397 }
8398
8399 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8400     _itc(itc),
8401     _bg(bg),_end(end)
8402 {
8403   if(_mesh)
8404     _mesh->incrRef();
8405 }
8406
8407 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8408 {
8409   if(_mesh)
8410     _mesh->decrRef();
8411 }
8412
8413 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8414 {
8415   return _type;
8416 }
8417
8418 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8419 {
8420   return _end-_bg;
8421 }
8422
8423 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8424 {
8425   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8426 }
8427
8428 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8429 {
8430   if(mesh)
8431     {
8432       mesh->incrRef();
8433       _nb_cell=mesh->getNumberOfCells();
8434     }
8435 }
8436
8437 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8438 {
8439   if(_mesh)
8440     _mesh->decrRef();
8441   delete _cell;
8442 }
8443
8444 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8445 {
8446   const int *c=_mesh->getNodalConnectivity()->begin();
8447   const int *ci=_mesh->getNodalConnectivityIndex()->begin();
8448   if(_cell_id<_nb_cell)
8449     {
8450       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8451       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
8452       int startId=_cell_id;
8453       _cell_id+=nbOfElems;
8454       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8455     }
8456   else
8457     return 0;
8458 }
8459
8460 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8461 {
8462   if(mesh)
8463     {
8464       _conn=mesh->getNodalConnectivity()->getPointer();
8465       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8466     }
8467 }
8468
8469 void MEDCouplingUMeshCell::next()
8470 {
8471   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8472     {
8473       _conn+=_conn_lgth;
8474       _conn_indx++;
8475     }
8476   _conn_lgth=_conn_indx[1]-_conn_indx[0];
8477 }
8478
8479 std::string MEDCouplingUMeshCell::repr() const
8480 {
8481   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8482     {
8483       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8484       oss << " : ";
8485       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8486       return oss.str();
8487     }
8488   else
8489     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8490 }
8491
8492 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8493 {
8494   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8495     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8496   else
8497     return INTERP_KERNEL::NORM_ERROR;
8498 }
8499
8500 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8501 {
8502   lgth=_conn_lgth;
8503   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8504     return _conn;
8505   else
8506     return 0;
8507 }