Salome HOME
Mesh::getNumberOfCells returns std::size_t
[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 (CEA/DEN)
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_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,-1,-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   int nbOfCellsToModify=(int)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   int nbOfCells=getNumberOfCells();
1994   bool easyAssign=true;
1995   const int *connI=_nodal_connec_index->getConstPointer();
1996   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1997   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1998     {
1999       if(*it>=0 && *it<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!=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   bool b=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       int 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(int cellId) const
2779 {
2780   const int *ptI=_nodal_connec_index->getConstPointer();
2781   const int *pt=_nodal_connec->getConstPointer();
2782   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2783     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2784   else
2785     {
2786       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2787       throw INTERP_KERNEL::Exception(oss.str());
2788     }
2789 }
2790
2791 /*!
2792  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2793  * This method does not throw exception if geometric type \a type is not in \a this.
2794  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2795  * The coordinates array is not considered here.
2796  *
2797  * \param [in] type the geometric type
2798  * \return cell ids in this having geometric type \a type.
2799  */
2800 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2801 {
2802
2803   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2804   ret->alloc(0,1);
2805   checkConnectivityFullyDefined();
2806   int nbCells=getNumberOfCells();
2807   int mdim=getMeshDimension();
2808   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2809   if(mdim!=(int)cm.getDimension())
2810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2811   const int *ptI=_nodal_connec_index->getConstPointer();
2812   const int *pt=_nodal_connec->getConstPointer();
2813   for(int i=0;i<nbCells;i++)
2814     {
2815       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2816         ret->pushBackSilent(i);
2817     }
2818   return ret.retn();
2819 }
2820
2821 /*!
2822  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2823  */
2824 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2825 {
2826   const int *ptI=_nodal_connec_index->getConstPointer();
2827   const int *pt=_nodal_connec->getConstPointer();
2828   int nbOfCells=getNumberOfCells();
2829   int ret=0;
2830   for(int i=0;i<nbOfCells;i++)
2831     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2832       ret++;
2833   return ret;
2834 }
2835
2836 /*!
2837  * Returns the nodal connectivity of a given cell.
2838  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2839  * all returned node ids can be used in getCoordinatesOfNode().
2840  *  \param [in] cellId - an id of the cell of interest.
2841  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2842  *         cleared before the appending.
2843  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2844  */
2845 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2846 {
2847   const int *ptI=_nodal_connec_index->getConstPointer();
2848   const int *pt=_nodal_connec->getConstPointer();
2849   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2850     if(*w>=0)
2851       conn.push_back(*w);
2852 }
2853
2854 std::string MEDCouplingUMesh::simpleRepr() const
2855 {
2856   static const char msg0[]="No coordinates specified !";
2857   std::ostringstream ret;
2858   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2859   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2860   int tmpp1,tmpp2;
2861   double tt=getTime(tmpp1,tmpp2);
2862   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2863   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2864   if(_mesh_dim>=-1)
2865     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2866   else
2867     { ret << " Mesh dimension has not been set or is invalid !"; }
2868   if(_coords!=0)
2869     {
2870       const int spaceDim=getSpaceDimension();
2871       ret << spaceDim << "\nInfo attached on space dimension : ";
2872       for(int i=0;i<spaceDim;i++)
2873         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2874       ret << "\n";
2875     }
2876   else
2877     ret << msg0 << "\n";
2878   ret << "Number of nodes : ";
2879   if(_coords!=0)
2880     ret << getNumberOfNodes() << "\n";
2881   else
2882     ret << msg0 << "\n";
2883   ret << "Number of cells : ";
2884   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2885     ret << getNumberOfCells() << "\n";
2886   else
2887     ret << "No connectivity specified !" << "\n";
2888   ret << "Cell types present : ";
2889   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2890     {
2891       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2892       ret << cm.getRepr() << " ";
2893     }
2894   ret << "\n";
2895   return ret.str();
2896 }
2897
2898 std::string MEDCouplingUMesh::advancedRepr() const
2899 {
2900   std::ostringstream ret;
2901   ret << simpleRepr();
2902   ret << "\nCoordinates array : \n___________________\n\n";
2903   if(_coords)
2904     _coords->reprWithoutNameStream(ret);
2905   else
2906     ret << "No array set !\n";
2907   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2908   reprConnectivityOfThisLL(ret);
2909   return ret.str();
2910 }
2911
2912 /*!
2913  * This method returns a C++ code that is a dump of \a this.
2914  * This method will throw if this is not fully defined.
2915  */
2916 std::string MEDCouplingUMesh::cppRepr() const
2917 {
2918   static const char coordsName[]="coords";
2919   static const char connName[]="conn";
2920   static const char connIName[]="connI";
2921   checkFullyDefined();
2922   std::ostringstream ret; ret << "// coordinates" << std::endl;
2923   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2924   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2925   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2926   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2927   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2928   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2929   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2930   return ret.str();
2931 }
2932
2933 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2934 {
2935   std::ostringstream ret;
2936   reprConnectivityOfThisLL(ret);
2937   return ret.str();
2938 }
2939
2940 /*!
2941  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2942  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2943  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2944  * some algos).
2945  * 
2946  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2947  * 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
2948  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2949  */
2950 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2951 {
2952   int mdim=getMeshDimension();
2953   if(mdim<0)
2954     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2955   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2956   MCAuto<DataArrayInt> tmp1,tmp2;
2957   bool needToCpyCT=true;
2958   if(!_nodal_connec)
2959     {
2960       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2961       needToCpyCT=false;
2962     }
2963   else
2964     {
2965       tmp1=_nodal_connec;
2966       tmp1->incrRef();
2967     }
2968   if(!_nodal_connec_index)
2969     {
2970       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2971       needToCpyCT=false;
2972     }
2973   else
2974     {
2975       tmp2=_nodal_connec_index;
2976       tmp2->incrRef();
2977     }
2978   ret->setConnectivity(tmp1,tmp2,false);
2979   if(needToCpyCT)
2980     ret->_types=_types;
2981   if(!_coords)
2982     {
2983       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2984       ret->setCoords(coords);
2985     }
2986   else
2987     ret->setCoords(_coords);
2988   return ret.retn();
2989 }
2990
2991 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2992 {
2993   const int *ptI=_nodal_connec_index->getConstPointer();
2994   const int *pt=_nodal_connec->getConstPointer();
2995   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2996     return ptI[cellId+1]-ptI[cellId]-1;
2997   else
2998     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2999 }
3000
3001 /*!
3002  * Returns types of cells of the specified part of \a this mesh.
3003  * This method avoids computing sub-mesh explicitely to get its types.
3004  *  \param [in] begin - an array of cell ids of interest.
3005  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3006  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3007  *         describing the cell types. 
3008  *  \throw If the coordinates array is not set.
3009  *  \throw If the nodal connectivity of cells is not defined.
3010  *  \sa getAllGeoTypes()
3011  */
3012 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3013 {
3014   checkFullyDefined();
3015   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3016   const int *conn=_nodal_connec->getConstPointer();
3017   const int *connIndex=_nodal_connec_index->getConstPointer();
3018   for(const int *w=begin;w!=end;w++)
3019     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3020   return ret;
3021 }
3022
3023 /*!
3024  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3025  * Optionally updates
3026  * a set of types of cells constituting \a this mesh. 
3027  * This method is for advanced users having prepared their connectivity before. For
3028  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3029  *  \param [in] conn - the nodal connectivity array. 
3030  *  \param [in] connIndex - the nodal connectivity index array.
3031  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3032  *         mesh is updated.
3033  */
3034 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3035 {
3036   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3037   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3038   if(isComputingTypes)
3039     computeTypes();
3040   declareAsNew();
3041 }
3042
3043 /*!
3044  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3045  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3046  */
3047 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3048     _nodal_connec(0),_nodal_connec_index(0),
3049     _types(other._types)
3050 {
3051   if(other._nodal_connec)
3052     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCopy);
3053   if(other._nodal_connec_index)
3054     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCopy);
3055 }
3056
3057 MEDCouplingUMesh::~MEDCouplingUMesh()
3058 {
3059   if(_nodal_connec)
3060     _nodal_connec->decrRef();
3061   if(_nodal_connec_index)
3062     _nodal_connec_index->decrRef();
3063 }
3064
3065 /*!
3066  * Recomputes a set of cell types of \a this mesh. For more info see
3067  * \ref MEDCouplingUMeshNodalConnectivity.
3068  */
3069 void MEDCouplingUMesh::computeTypes()
3070 {
3071   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3072 }
3073
3074
3075 /*!
3076  * Returns a number of cells constituting \a this mesh. 
3077  *  \return int - the number of cells in \a this mesh.
3078  *  \throw If the nodal connectivity of cells is not defined.
3079  */
3080 std::size_t MEDCouplingUMesh::getNumberOfCells() const
3081
3082   if(_nodal_connec_index)
3083     return _nodal_connec_index->getNumberOfTuples()-1;
3084   else
3085     if(_mesh_dim==-1)
3086       return 1;
3087     else
3088       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3089 }
3090
3091 /*!
3092  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3093  * mesh. For more info see \ref meshes.
3094  *  \return int - the dimension of \a this mesh.
3095  *  \throw If the mesh dimension is not defined using setMeshDimension().
3096  */
3097 int MEDCouplingUMesh::getMeshDimension() const
3098 {
3099   if(_mesh_dim<-1)
3100     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3101   return _mesh_dim;
3102 }
3103
3104 /*!
3105  * Returns a length of the nodal connectivity array.
3106  * This method is for test reason. Normally the integer returned is not useable by
3107  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3108  *  \return int - the length of the nodal connectivity array.
3109  */
3110 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3111 {
3112   return _nodal_connec->getNbOfElems();
3113 }
3114
3115 /*!
3116  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3117  */
3118 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3119 {
3120   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3121   tinyInfo.push_back(getMeshDimension());
3122   tinyInfo.push_back(getNumberOfCells());
3123   if(_nodal_connec)
3124     tinyInfo.push_back(getNodalConnectivityArrayLen());
3125   else
3126     tinyInfo.push_back(-1);
3127 }
3128
3129 /*!
3130  * First step of unserialization process.
3131  */
3132 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3133 {
3134   return tinyInfo[6]<=0;
3135 }
3136
3137 /*!
3138  * Second step of serialization process.
3139  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3140  * \param a1
3141  * \param a2
3142  * \param littleStrings
3143  */
3144 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3145 {
3146   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3147   if(tinyInfo[5]!=-1)
3148     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3149 }
3150
3151 /*!
3152  * Third and final step of serialization process.
3153  */
3154 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3155 {
3156   MEDCouplingPointSet::serialize(a1,a2);
3157   if(getMeshDimension()>-1)
3158     {
3159       a1=DataArrayInt::New();
3160       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3161       int *ptA1=a1->getPointer();
3162       const int *conn=getNodalConnectivity()->getConstPointer();
3163       const int *index=getNodalConnectivityIndex()->getConstPointer();
3164       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3165       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3166     }
3167   else
3168     a1=0;
3169 }
3170
3171 /*!
3172  * Second and final unserialization process.
3173  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3174  */
3175 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3176 {
3177   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3178   setMeshDimension(tinyInfo[5]);
3179   if(tinyInfo[7]!=-1)
3180     {
3181       // Connectivity
3182       const int *recvBuffer=a1->getConstPointer();
3183       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3184       myConnecIndex->alloc(tinyInfo[6]+1,1);
3185       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3186       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3187       myConnec->alloc(tinyInfo[7],1);
3188       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3189       setConnectivity(myConnec, myConnecIndex);
3190     }
3191 }
3192
3193
3194
3195 /*!
3196  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3197  * mesh.<br>
3198  * For 1D cells, the returned field contains lengths.<br>
3199  * For 2D cells, the returned field contains areas.<br>
3200  * For 3D cells, the returned field contains volumes.
3201  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3202  *         orientation, i.e. the volume is always positive.
3203  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3204  *         and one time . The caller is to delete this field using decrRef() as it is no
3205  *         more needed.
3206  */
3207 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3208 {
3209   std::string name="MeasureOfMesh_";
3210   name+=getName();
3211   int nbelem=getNumberOfCells();
3212   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3213   field->setName(name);
3214   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3215   array->alloc(nbelem,1);
3216   double *area_vol=array->getPointer();
3217   field->setArray(array) ; array=0;
3218   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3219   field->synchronizeTimeWithMesh();
3220   if(getMeshDimension()!=-1)
3221     {
3222       int ipt;
3223       INTERP_KERNEL::NormalizedCellType type;
3224       int dim_space=getSpaceDimension();
3225       const double *coords=getCoords()->getConstPointer();
3226       const int *connec=getNodalConnectivity()->getConstPointer();
3227       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3228       for(int iel=0;iel<nbelem;iel++)
3229         {
3230           ipt=connec_index[iel];
3231           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3232           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);
3233         }
3234       if(isAbs)
3235         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3236     }
3237   else
3238     {
3239       area_vol[0]=std::numeric_limits<double>::max();
3240     }
3241   return field.retn();
3242 }
3243
3244 /*!
3245  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3246  * mesh.<br>
3247  * For 1D cells, the returned array contains lengths.<br>
3248  * For 2D cells, the returned array contains areas.<br>
3249  * For 3D cells, the returned array contains volumes.
3250  * This method avoids building explicitly a part of \a this mesh to perform the work.
3251  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3252  *         orientation, i.e. the volume is always positive.
3253  *  \param [in] begin - an array of cell ids of interest.
3254  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3255  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3256  *          delete this array using decrRef() as it is no more needed.
3257  * 
3258  *  \if ENABLE_EXAMPLES
3259  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3260  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3261  *  \endif
3262  *  \sa getMeasureField()
3263  */
3264 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3265 {
3266   std::string name="PartMeasureOfMesh_";
3267   name+=getName();
3268   int nbelem=(int)std::distance(begin,end);
3269   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3270   array->setName(name);
3271   array->alloc(nbelem,1);
3272   double *area_vol=array->getPointer();
3273   if(getMeshDimension()!=-1)
3274     {
3275       int ipt;
3276       INTERP_KERNEL::NormalizedCellType type;
3277       int dim_space=getSpaceDimension();
3278       const double *coords=getCoords()->getConstPointer();
3279       const int *connec=getNodalConnectivity()->getConstPointer();
3280       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3281       for(const int *iel=begin;iel!=end;iel++)
3282         {
3283           ipt=connec_index[*iel];
3284           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3285           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3286         }
3287       if(isAbs)
3288         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3289     }
3290   else
3291     {
3292       area_vol[0]=std::numeric_limits<double>::max();
3293     }
3294   return array.retn();
3295 }
3296
3297 /*!
3298  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3299  * \a this one. The returned field contains the dual cell volume for each corresponding
3300  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3301  *  the dual mesh in P1 sens of \a this.<br>
3302  * For 1D cells, the returned field contains lengths.<br>
3303  * For 2D cells, the returned field contains areas.<br>
3304  * For 3D cells, the returned field contains volumes.
3305  * This method is useful to check "P1*" conservative interpolators.
3306  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3307  *         orientation, i.e. the volume is always positive.
3308  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3309  *          nodes and one time. The caller is to delete this array using decrRef() as
3310  *          it is no more needed.
3311  */
3312 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3313 {
3314   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3315   std::string name="MeasureOnNodeOfMesh_";
3316   name+=getName();
3317   int nbNodes=getNumberOfNodes();
3318   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3319   double cst=1./((double)getMeshDimension()+1.);
3320   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3321   array->alloc(nbNodes,1);
3322   double *valsToFill=array->getPointer();
3323   std::fill(valsToFill,valsToFill+nbNodes,0.);
3324   const double *values=tmp->getArray()->getConstPointer();
3325   MCAuto<DataArrayInt> da=DataArrayInt::New();
3326   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3327   getReverseNodalConnectivity(da,daInd);
3328   const int *daPtr=da->getConstPointer();
3329   const int *daIPtr=daInd->getConstPointer();
3330   for(int i=0;i<nbNodes;i++)
3331     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3332       valsToFill[i]+=cst*values[*cell];
3333   ret->setMesh(this);
3334   ret->setArray(array);
3335   return ret.retn();
3336 }
3337
3338 /*!
3339  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3340  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3341  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3342  * and are normalized.
3343  * <br> \a this can be either 
3344  * - a  2D mesh in 2D or 3D space or 
3345  * - an 1D mesh in 2D space.
3346  * 
3347  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3348  *          cells and one time. The caller is to delete this field using decrRef() as
3349  *          it is no more needed.
3350  *  \throw If the nodal connectivity of cells is not defined.
3351  *  \throw If the coordinates array is not set.
3352  *  \throw If the mesh dimension is not set.
3353  *  \throw If the mesh and space dimension is not as specified above.
3354  */
3355 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3356 {
3357   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3358     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3359   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3360   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3361   int nbOfCells=getNumberOfCells();
3362   int nbComp=getMeshDimension()+1;
3363   array->alloc(nbOfCells,nbComp);
3364   double *vals=array->getPointer();
3365   const int *connI=_nodal_connec_index->getConstPointer();
3366   const int *conn=_nodal_connec->getConstPointer();
3367   const double *coords=_coords->getConstPointer();
3368   if(getMeshDimension()==2)
3369     {
3370       if(getSpaceDimension()==3)
3371         {
3372           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3373           const double *locPtr=loc->getConstPointer();
3374           for(int i=0;i<nbOfCells;i++,vals+=3)
3375             {
3376               int offset=connI[i];
3377               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3378               double n=INTERP_KERNEL::norm<3>(vals);
3379               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3380             }
3381         }
3382       else
3383         {
3384           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3385           const double *isAbsPtr=isAbs->getArray()->begin();
3386           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3387             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3388         }
3389     }
3390   else//meshdimension==1
3391     {
3392       double tmp[2];
3393       for(int i=0;i<nbOfCells;i++)
3394         {
3395           int offset=connI[i];
3396           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3397           double n=INTERP_KERNEL::norm<2>(tmp);
3398           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3399           *vals++=-tmp[1];
3400           *vals++=tmp[0];
3401         }
3402     }
3403   ret->setArray(array);
3404   ret->setMesh(this);
3405   ret->synchronizeTimeWithSupport();
3406   return ret.retn();
3407 }
3408
3409 /*!
3410  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3411  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3412  * and are normalized.
3413  * <br> \a this can be either 
3414  * - a  2D mesh in 2D or 3D space or 
3415  * - an 1D mesh in 2D space.
3416  * 
3417  * This method avoids building explicitly a part of \a this mesh to perform the work.
3418  *  \param [in] begin - an array of cell ids of interest.
3419  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3420  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3421  *          cells and one time. The caller is to delete this field using decrRef() as
3422  *          it is no more needed.
3423  *  \throw If the nodal connectivity of cells is not defined.
3424  *  \throw If the coordinates array is not set.
3425  *  \throw If the mesh dimension is not set.
3426  *  \throw If the mesh and space dimension is not as specified above.
3427  *  \sa buildOrthogonalField()
3428  *
3429  *  \if ENABLE_EXAMPLES
3430  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3431  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3432  *  \endif
3433  */
3434 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3435 {
3436   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3437     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3438   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3439   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3440   std::size_t nbelems=std::distance(begin,end);
3441   int nbComp=getMeshDimension()+1;
3442   array->alloc((int)nbelems,nbComp);
3443   double *vals=array->getPointer();
3444   const int *connI=_nodal_connec_index->getConstPointer();
3445   const int *conn=_nodal_connec->getConstPointer();
3446   const double *coords=_coords->getConstPointer();
3447   if(getMeshDimension()==2)
3448     {
3449       if(getSpaceDimension()==3)
3450         {
3451           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3452           const double *locPtr=loc->getConstPointer();
3453           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3454             {
3455               int offset=connI[*i];
3456               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3457               double n=INTERP_KERNEL::norm<3>(vals);
3458               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3459             }
3460         }
3461       else
3462         {
3463           for(std::size_t i=0;i<nbelems;i++)
3464             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3465         }
3466     }
3467   else//meshdimension==1
3468     {
3469       double tmp[2];
3470       for(const int *i=begin;i!=end;i++)
3471         {
3472           int offset=connI[*i];
3473           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3474           double n=INTERP_KERNEL::norm<2>(tmp);
3475           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3476           *vals++=-tmp[1];
3477           *vals++=tmp[0];
3478         }
3479     }
3480   ret->setArray(array);
3481   ret->setMesh(this);
3482   ret->synchronizeTimeWithSupport();
3483   return ret.retn();
3484 }
3485
3486 /*!
3487  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3488  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3489  * and are \b not normalized.
3490  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3491  *          cells and one time. The caller is to delete this field using decrRef() as
3492  *          it is no more needed.
3493  *  \throw If the nodal connectivity of cells is not defined.
3494  *  \throw If the coordinates array is not set.
3495  *  \throw If \a this->getMeshDimension() != 1.
3496  *  \throw If \a this mesh includes cells of type other than SEG2.
3497  */
3498 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3499 {
3500   if(getMeshDimension()!=1)
3501     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3502   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3503     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3504   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3505   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3506   int nbOfCells=getNumberOfCells();
3507   int spaceDim=getSpaceDimension();
3508   array->alloc(nbOfCells,spaceDim);
3509   double *pt=array->getPointer();
3510   const double *coo=getCoords()->getConstPointer();
3511   std::vector<int> conn;
3512   conn.reserve(2);
3513   for(int i=0;i<nbOfCells;i++)
3514     {
3515       conn.resize(0);
3516       getNodeIdsOfCell(i,conn);
3517       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3518     }
3519   ret->setArray(array);
3520   ret->setMesh(this);
3521   ret->synchronizeTimeWithSupport();
3522   return ret.retn();
3523 }
3524
3525 /*!
3526  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3527  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3528  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3529  * from. If a result face is shared by two 3D cells, then the face in included twice in
3530  * the result mesh.
3531  *  \param [in] origin - 3 components of a point defining location of the plane.
3532  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3533  *         must be greater than 1e-6.
3534  *  \param [in] eps - half-thickness of the plane.
3535  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3536  *         producing correspondent 2D cells. The caller is to delete this array
3537  *         using decrRef() as it is no more needed.
3538  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3539  *         not share the node coordinates array with \a this mesh. The caller is to
3540  *         delete this mesh using decrRef() as it is no more needed.  
3541  *  \throw If the coordinates array is not set.
3542  *  \throw If the nodal connectivity of cells is not defined.
3543  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3544  *  \throw If magnitude of \a vec is less than 1e-6.
3545  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3546  *  \throw If \a this includes quadratic cells.
3547  */
3548 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3549 {
3550   checkFullyDefined();
3551   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3552     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3553   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3554   if(candidates->empty())
3555     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3556   std::vector<int> nodes;
3557   DataArrayInt *cellIds1D=0;
3558   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3559   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3560   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3561   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3562   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3563   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3564   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3565   revDesc2=0; revDescIndx2=0;
3566   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3567   revDesc1=0; revDescIndx1=0;
3568   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3569   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3570   //
3571   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3572   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3573     cut3DCurve[*it]=-1;
3574   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3575   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3576   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3577                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3578                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3579   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3580   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3581   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3582   if(cellIds2->empty())
3583     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3584   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3585   ret->setCoords(mDesc1->getCoords());
3586   ret->setConnectivity(conn,connI,true);
3587   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3588   return ret.retn();
3589 }
3590
3591 /*!
3592  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3593 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
3594 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3595 the result mesh.
3596  *  \param [in] origin - 3 components of a point defining location of the plane.
3597  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3598  *         must be greater than 1e-6.
3599  *  \param [in] eps - half-thickness of the plane.
3600  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3601  *         producing correspondent segments. The caller is to delete this array
3602  *         using decrRef() as it is no more needed.
3603  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3604  *         mesh in 3D space. This mesh does not share the node coordinates array with
3605  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3606  *         no more needed. 
3607  *  \throw If the coordinates array is not set.
3608  *  \throw If the nodal connectivity of cells is not defined.
3609  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3610  *  \throw If magnitude of \a vec is less than 1e-6.
3611  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3612  *  \throw If \a this includes quadratic cells.
3613  */
3614 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3615 {
3616   checkFullyDefined();
3617   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3618     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3619   MCAuto<DataArrayInt> candidates(getCellIdsCrossingPlane(origin,vec,eps));
3620   if(candidates->empty())
3621     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3622   std::vector<int> nodes;
3623   DataArrayInt *cellIds1D(0);
3624   MCAuto<MEDCouplingUMesh> subMesh(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3625   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3626   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
3627   MCAuto<MEDCouplingUMesh> mDesc1(subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3628   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3629   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3630   //
3631   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3632   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3633     cut3DCurve[*it]=-1;
3634   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3635   int ncellsSub=subMesh->getNumberOfCells();
3636   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3637   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3638                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3639                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3640   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3641   conn->alloc(0,1);
3642   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3643   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3644   for(int i=0;i<ncellsSub;i++)
3645     {
3646       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3647         {
3648           if(cut3DSurf[i].first!=-2)
3649             {
3650               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3651               connI->pushBackSilent(conn->getNumberOfTuples());
3652               cellIds2->pushBackSilent(i);
3653             }
3654           else
3655             {
3656               int cellId3DSurf=cut3DSurf[i].second;
3657               int offset=nodalI[cellId3DSurf]+1;
3658               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3659               for(int j=0;j<nbOfEdges;j++)
3660                 {
3661                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3662                   connI->pushBackSilent(conn->getNumberOfTuples());
3663                   cellIds2->pushBackSilent(cellId3DSurf);
3664                 }
3665             }
3666         }
3667     }
3668   if(cellIds2->empty())
3669     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3670   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3671   ret->setCoords(mDesc1->getCoords());
3672   ret->setConnectivity(conn,connI,true);
3673   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3674   return ret.retn();
3675 }
3676
3677 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::clipSingle3DCellByPlane(const double origin[3], const double vec[3], double eps) const
3678 {
3679   checkFullyDefined();
3680   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3681     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3682   if(getNumberOfCells()!=1)
3683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works only on mesh containing exactly one cell !");
3684   //
3685   std::vector<int> nodes;
3686   findNodesOnPlane(origin,vec,eps,nodes);
3687   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());
3688   MCAuto<MEDCouplingUMesh> mDesc2(buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2));//meshDim==2 spaceDim==3
3689   revDesc2=0; revDescIndx2=0;
3690   MCAuto<MEDCouplingUMesh> mDesc1(mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3691   revDesc1=0; revDescIndx1=0;
3692   DataArrayInt *cellIds1D(0);
3693   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3694   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3695   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3696   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3697     cut3DCurve[*it]=-1;
3698   bool sameNbNodes;
3699   {
3700     int oldNbNodes(mDesc1->getNumberOfNodes());
3701     mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3702     sameNbNodes=(mDesc1->getNumberOfNodes()==oldNbNodes);
3703   }
3704   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3705   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->begin(),mDesc2->getNodalConnectivityIndex()->begin(),
3706                               mDesc1->getNodalConnectivity()->begin(),mDesc1->getNodalConnectivityIndex()->begin(),
3707                               desc1->begin(),descIndx1->begin(),cut3DSurf);
3708   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New());
3709   connI->pushBackSilent(0); conn->alloc(0,1);
3710   {
3711     MCAuto<DataArrayInt> cellIds2(DataArrayInt::New()); cellIds2->alloc(0,1);
3712     assemblyForSplitFrom3DSurf(cut3DSurf,desc2->begin(),descIndx2->begin(),conn,connI,cellIds2);
3713     if(cellIds2->empty())
3714       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3715   }
3716   std::vector<std::vector<int> > res;
3717   buildSubCellsFromCut(cut3DSurf,desc2->begin(),descIndx2->begin(),mDesc1->getCoords()->begin(),eps,res);
3718   std::size_t sz(res.size());
3719   if(res.size()==mDesc1->getNumberOfCells() && sameNbNodes)
3720     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane : cell is not clipped !");
3721   for(std::size_t i=0;i<sz;i++)
3722     {
3723       conn->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
3724       conn->insertAtTheEnd(res[i].begin(),res[i].end());
3725       connI->pushBackSilent(conn->getNumberOfTuples());
3726     }
3727   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
3728   ret->setCoords(mDesc1->getCoords());
3729   ret->setConnectivity(conn,connI,true);
3730   int nbCellsRet(ret->getNumberOfCells());
3731   //
3732   MCAuto<DataArrayDouble> vec2(DataArrayDouble::New()); vec2->alloc(1,3); std::copy(vec,vec+3,vec2->getPointer());
3733   MCAuto<MEDCouplingFieldDouble> ortho(ret->buildOrthogonalField());
3734   MCAuto<DataArrayDouble> ortho2(ortho->getArray()->selectByTupleIdSafeSlice(0,1,1));
3735   MCAuto<DataArrayDouble> dott(DataArrayDouble::Dot(ortho2,vec2));
3736   MCAuto<DataArrayDouble> ccm(ret->computeCellCenterOfMass());
3737   MCAuto<DataArrayDouble> occm;
3738   {
3739     MCAuto<DataArrayDouble> pt(DataArrayDouble::New()); pt->alloc(1,3); std::copy(origin,origin+3,pt->getPointer());
3740     occm=DataArrayDouble::Substract(ccm,pt);
3741   }
3742   vec2=DataArrayDouble::New(); vec2->alloc(nbCellsRet,3);
3743   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);
3744   MCAuto<DataArrayDouble> dott2(DataArrayDouble::Dot(occm,vec2));
3745   //
3746   const int *cPtr(ret->getNodalConnectivity()->begin()),*ciPtr(ret->getNodalConnectivityIndex()->begin());
3747   MCAuto<MEDCouplingUMesh> ret2(MEDCouplingUMesh::New("Clip3D",3));
3748   ret2->setCoords(mDesc1->getCoords());
3749   MCAuto<DataArrayInt> conn2(DataArrayInt::New()),conn2I(DataArrayInt::New());
3750   conn2I->pushBackSilent(0); conn2->alloc(0,1);
3751   std::vector<int> cell0(1,(int)INTERP_KERNEL::NORM_POLYHED);
3752   std::vector<int> cell1(1,(int)INTERP_KERNEL::NORM_POLYHED);
3753   if(dott->getIJ(0,0)>0)
3754     {
3755       cell0.insert(cell0.end(),cPtr+1,cPtr+ciPtr[1]);
3756       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell1,cell1.end()));
3757     }
3758   else
3759     {
3760       cell1.insert(cell1.end(),cPtr+1,cPtr+ciPtr[1]);
3761       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell0,cell0.end()));
3762     }
3763   for(int i=1;i<nbCellsRet;i++)
3764     {
3765       if(dott2->getIJ(i,0)<0)
3766         {
3767           if(ciPtr[i+1]-ciPtr[i]>=4)
3768             {
3769               cell0.push_back(-1);
3770               cell0.insert(cell0.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3771             }
3772         }
3773       else
3774         {
3775           if(ciPtr[i+1]-ciPtr[i]>=4)
3776             {
3777               cell1.push_back(-1);
3778               cell1.insert(cell1.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3779             }
3780         }
3781     }
3782   conn2->insertAtTheEnd(cell0.begin(),cell0.end());
3783   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3784   conn2->insertAtTheEnd(cell1.begin(),cell1.end());
3785   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3786   ret2->setConnectivity(conn2,conn2I,true);
3787   ret2->checkConsistencyLight();
3788   ret2->orientCorrectlyPolyhedrons();
3789   return ret2;
3790 }
3791
3792 /*!
3793  * Finds cells whose bounding boxes intersect a given plane.
3794  *  \param [in] origin - 3 components of a point defining location of the plane.
3795  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3796  *         must be greater than 1e-6.
3797  *  \param [in] eps - half-thickness of the plane.
3798  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3799  *         cells. The caller is to delete this array using decrRef() as it is no more
3800  *         needed.
3801  *  \throw If the coordinates array is not set.
3802  *  \throw If the nodal connectivity of cells is not defined.
3803  *  \throw If \a this->getSpaceDimension() != 3.
3804  *  \throw If magnitude of \a vec is less than 1e-6.
3805  *  \sa buildSlice3D()
3806  */
3807 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3808 {
3809   checkFullyDefined();
3810   if(getSpaceDimension()!=3)
3811     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3812   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3813   if(normm<1e-6)
3814     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3815   double vec2[3];
3816   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3817   double angle=acos(vec[2]/normm);
3818   MCAuto<DataArrayInt> cellIds;
3819   double bbox[6];
3820   if(angle>eps)
3821     {
3822       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3823       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3824       if(normm2/normm>1e-6)
3825         DataArrayDouble::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer(),coo->getPointer());
3826       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3827       mw->setCoords(coo);
3828       mw->getBoundingBox(bbox);
3829       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3830       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3831     }
3832   else
3833     {
3834       getBoundingBox(bbox);
3835       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3836       cellIds=getCellsInBoundingBox(bbox,eps);
3837     }
3838   return cellIds.retn();
3839 }
3840
3841 /*!
3842  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3843  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3844  * No consideration of coordinate is done by this method.
3845  * 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)
3846  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
3847  */
3848 bool MEDCouplingUMesh::isContiguous1D() const
3849 {
3850   if(getMeshDimension()!=1)
3851     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3852   int nbCells=getNumberOfCells();
3853   if(nbCells<1)
3854     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3855   const int *connI(_nodal_connec_index->begin()),*conn(_nodal_connec->begin());
3856   int ref=conn[connI[0]+2];
3857   for(int i=1;i<nbCells;i++)
3858     {
3859       if(conn[connI[i]+1]!=ref)
3860         return false;
3861       ref=conn[connI[i]+2];
3862     }
3863   return true;
3864 }
3865
3866 /*!
3867  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3868  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3869  * \param pt reference point of the line
3870  * \param v normalized director vector of the line
3871  * \param eps max precision before throwing an exception
3872  * \param res output of size this->getNumberOfCells
3873  */
3874 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3875 {
3876   if(getMeshDimension()!=1)
3877     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3878   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3879     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3880   if(getSpaceDimension()!=3)
3881     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3882   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3883   const double *fPtr=f->getArray()->getConstPointer();
3884   double tmp[3];
3885   for(int i=0;i<getNumberOfCells();i++)
3886     {
3887       const double *tmp1=fPtr+3*i;
3888       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3889       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3890       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3891       double n1=INTERP_KERNEL::norm<3>(tmp);
3892       n1/=INTERP_KERNEL::norm<3>(tmp1);
3893       if(n1>eps)
3894         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3895     }
3896   const double *coo=getCoords()->getConstPointer();
3897   for(int i=0;i<getNumberOfNodes();i++)
3898     {
3899       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3900       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3901       res[i]=std::accumulate(tmp,tmp+3,0.);
3902     }
3903 }
3904
3905 /*!
3906  * 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. 
3907  * \a this is expected to be a mesh so that its space dimension is equal to its
3908  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3909  * 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).
3910  *
3911  * 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
3912  * 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).
3913  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3914  *
3915  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3916  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3917  *
3918  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3919  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3920  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3921  * \return the positive value of the distance.
3922  * \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
3923  * dimension - 1.
3924  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3925  */
3926 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3927 {
3928   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3929   if(meshDim!=spaceDim-1)
3930     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3931   if(meshDim!=2 && meshDim!=1)
3932     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3933   checkFullyDefined();
3934   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3935     { 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()); }
3936   DataArrayInt *ret1=0;
3937   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3938   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3939   MCAuto<DataArrayInt> ret1Safe(ret1);
3940   cellId=*ret1Safe->begin();
3941   return *ret0->begin();
3942 }
3943
3944 /*!
3945  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3946  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3947  * 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
3948  * 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).
3949  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3950  * 
3951  * \a this is expected to be a mesh so that its space dimension is equal to its
3952  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3953  * 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).
3954  *
3955  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3956  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3957  *
3958  * \param [in] pts the list of points in which each tuple represents a point
3959  * \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.
3960  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3961  * \throw if number of components of \a pts is not equal to the space dimension.
3962  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3963  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3964  */
3965 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3966 {
3967   if(!pts)
3968     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3969   pts->checkAllocated();
3970   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3971   if(meshDim!=spaceDim-1)
3972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3973   if(meshDim!=2 && meshDim!=1)
3974     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3975   if(pts->getNumberOfComponents()!=spaceDim)
3976     {
3977       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3978       throw INTERP_KERNEL::Exception(oss.str());
3979     }
3980   checkFullyDefined();
3981   int nbCells=getNumberOfCells();
3982   if(nbCells==0)
3983     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3984   int nbOfPts=pts->getNumberOfTuples();
3985   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3986   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3987   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3988   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3989   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3990   const double *bbox(bboxArr->begin());
3991   switch(spaceDim)
3992   {
3993     case 3:
3994       {
3995         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3996         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3997           {
3998             double x=std::numeric_limits<double>::max();
3999             std::vector<int> elems;
4000             myTree.getMinDistanceOfMax(ptsPtr,x);
4001             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4002             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4003           }
4004         break;
4005       }
4006     case 2:
4007       {
4008         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4009         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4010           {
4011             double x=std::numeric_limits<double>::max();
4012             std::vector<int> elems;
4013             myTree.getMinDistanceOfMax(ptsPtr,x);
4014             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4015             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4016           }
4017         break;
4018       }
4019     default:
4020       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4021   }
4022   cellIds=ret1.retn();
4023   return ret0.retn();
4024 }
4025
4026 /// @cond INTERNAL
4027
4028 /// @endcond
4029
4030 /*!
4031  * Finds cells in contact with a ball (i.e. a point with precision). 
4032  * 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.
4033  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4034  *
4035  * \warning This method is suitable if the caller intends to evaluate only one
4036  *          point, for more points getCellsContainingPoints() is recommended as it is
4037  *          faster. 
4038  *  \param [in] pos - array of coordinates of the ball central point.
4039  *  \param [in] eps - ball radius.
4040  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4041  *         if there are no such cells.
4042  *  \throw If the coordinates array is not set.
4043  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4044  */
4045 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4046 {
4047   std::vector<int> elts;
4048   getCellsContainingPoint(pos,eps,elts);
4049   if(elts.empty())
4050     return -1;
4051   return elts.front();
4052 }
4053
4054 /*!
4055  * Finds cells in contact with a ball (i.e. a point with precision).
4056  * 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.
4057  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4058  * \warning This method is suitable if the caller intends to evaluate only one
4059  *          point, for more points getCellsContainingPoints() is recommended as it is
4060  *          faster. 
4061  *  \param [in] pos - array of coordinates of the ball central point.
4062  *  \param [in] eps - ball radius.
4063  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4064  *         before inserting ids.
4065  *  \throw If the coordinates array is not set.
4066  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4067  *
4068  *  \if ENABLE_EXAMPLES
4069  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4070  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4071  *  \endif
4072  */
4073 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4074 {
4075   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4076   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4077   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4078 }
4079
4080 /*!
4081  * Finds cells in contact with several balls (i.e. points with precision).
4082  * This method is an extension of getCellContainingPoint() and
4083  * getCellsContainingPoint() for the case of multiple points.
4084  * 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.
4085  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4086  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4087  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4088  *         this->getSpaceDimension() * \a nbOfPoints 
4089  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4090  *  \param [in] eps - radius of balls (i.e. the precision).
4091  *  \param [out] elts - vector returning ids of found cells.
4092  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4093  *         dividing cell ids in \a elts into groups each referring to one
4094  *         point. Its every element (except the last one) is an index pointing to the
4095  *         first id of a group of cells. For example cells in contact with the *i*-th
4096  *         point are described by following range of indices:
4097  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4098  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4099  *         Number of cells in contact with the *i*-th point is
4100  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4101  *  \throw If the coordinates array is not set.
4102  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4103  *
4104  *  \if ENABLE_EXAMPLES
4105  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4106  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4107  *  \endif
4108  */
4109 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4110                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4111 {
4112   int spaceDim=getSpaceDimension();
4113   int mDim=getMeshDimension();
4114   if(spaceDim==3)
4115     {
4116       if(mDim==3)
4117         {
4118           const double *coords=_coords->getConstPointer();
4119           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4120         }
4121       /*else if(mDim==2)
4122         {
4123
4124         }*/
4125       else
4126         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4127     }
4128   else if(spaceDim==2)
4129     {
4130       if(mDim==2)
4131         {
4132           const double *coords=_coords->getConstPointer();
4133           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4134         }
4135       else
4136         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4137     }
4138   else if(spaceDim==1)
4139     {
4140       if(mDim==1)
4141         {
4142           const double *coords=_coords->getConstPointer();
4143           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4144         }
4145       else
4146         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4147     }
4148   else
4149     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4150 }
4151
4152 /*!
4153  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4154  * least two its edges intersect each other anywhere except their extremities. An
4155  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4156  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4157  *         cleared before filling in.
4158  *  \param [in] eps - precision.
4159  *  \throw If \a this->getMeshDimension() != 2.
4160  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4161  */
4162 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4163 {
4164   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4165   if(getMeshDimension()!=2)
4166     throw INTERP_KERNEL::Exception(msg);
4167   int spaceDim=getSpaceDimension();
4168   if(spaceDim!=2 && spaceDim!=3)
4169     throw INTERP_KERNEL::Exception(msg);
4170   const int *conn=_nodal_connec->getConstPointer();
4171   const int *connI=_nodal_connec_index->getConstPointer();
4172   int nbOfCells=getNumberOfCells();
4173   std::vector<double> cell2DinS2;
4174   for(int i=0;i<nbOfCells;i++)
4175     {
4176       int offset=connI[i];
4177       int nbOfNodesForCell=connI[i+1]-offset-1;
4178       if(nbOfNodesForCell<=3)
4179         continue;
4180       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4181       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4182       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4183         cells.push_back(i);
4184       cell2DinS2.clear();
4185     }
4186 }
4187
4188 /*!
4189  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4190  *
4191  * 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.
4192  * 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.
4193  * 
4194  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4195  * This convex envelop is computed using Jarvis march algorithm.
4196  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4197  * 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)
4198  * 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.
4199  *
4200  * \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.
4201  * \sa MEDCouplingUMesh::colinearize2D
4202  */
4203 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4204 {
4205   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4206     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4207   checkFullyDefined();
4208   const double *coords=getCoords()->getConstPointer();
4209   int nbOfCells=getNumberOfCells();
4210   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4211   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4212   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4213   int *workIndexOut=nodalConnecIndexOut->getPointer();
4214   *workIndexOut=0;
4215   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4216   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4217   std::set<INTERP_KERNEL::NormalizedCellType> types;
4218   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4219   isChanged->alloc(0,1);
4220   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4221     {
4222       int pos=nodalConnecOut->getNumberOfTuples();
4223       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4224         isChanged->pushBackSilent(i);
4225       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4226       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4227     }
4228   if(isChanged->empty())
4229     return 0;
4230   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4231   _types=types;
4232   return isChanged.retn();
4233 }
4234
4235 /*!
4236  * This method is \b NOT const because it can modify \a this.
4237  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4238  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4239  * \param policy specifies the type of extrusion chosen:
4240  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4241  *   will be repeated to build each level
4242  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4243  *   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
4244  *   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
4245  *   arc.
4246  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4247  */
4248 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4249 {
4250   checkFullyDefined();
4251   mesh1D->checkFullyDefined();
4252   if(!mesh1D->isContiguous1D())
4253     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4254   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4255     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4256   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4257     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4258   if(mesh1D->getMeshDimension()!=1)
4259     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4260   bool isQuad=false;
4261   if(isPresenceOfQuadratic())
4262     {
4263       if(mesh1D->isFullyQuadratic())
4264         isQuad=true;
4265       else
4266         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4267     }
4268   int oldNbOfNodes(getNumberOfNodes());
4269   MCAuto<DataArrayDouble> newCoords;
4270   switch(policy)
4271   {
4272     case 0:
4273       {
4274         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4275         break;
4276       }
4277     case 1:
4278       {
4279         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4280         break;
4281       }
4282     default:
4283       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4284   }
4285   setCoords(newCoords);
4286   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4287   updateTime();
4288   return ret.retn();
4289 }
4290
4291
4292 /*!
4293  * Checks if \a this mesh is constituted by only quadratic cells.
4294  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4295  *  \throw If the coordinates array is not set.
4296  *  \throw If the nodal connectivity of cells is not defined.
4297  */
4298 bool MEDCouplingUMesh::isFullyQuadratic() const
4299 {
4300   checkFullyDefined();
4301   bool ret=true;
4302   int nbOfCells=getNumberOfCells();
4303   for(int i=0;i<nbOfCells && ret;i++)
4304     {
4305       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4306       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4307       ret=cm.isQuadratic();
4308     }
4309   return ret;
4310 }
4311
4312 /*!
4313  * Checks if \a this mesh includes any quadratic cell.
4314  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4315  *  \throw If the coordinates array is not set.
4316  *  \throw If the nodal connectivity of cells is not defined.
4317  */
4318 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4319 {
4320   checkFullyDefined();
4321   bool ret=false;
4322   int nbOfCells=getNumberOfCells();
4323   for(int i=0;i<nbOfCells && !ret;i++)
4324     {
4325       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4326       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4327       ret=cm.isQuadratic();
4328     }
4329   return ret;
4330 }
4331
4332 /*!
4333  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4334  * this mesh, it remains unchanged.
4335  *  \throw If the coordinates array is not set.
4336  *  \throw If the nodal connectivity of cells is not defined.
4337  */
4338 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4339 {
4340   checkFullyDefined();
4341   int nbOfCells(getNumberOfCells());
4342   int delta=0;
4343   const int *iciptr=_nodal_connec_index->begin();
4344   for(int i=0;i<nbOfCells;i++)
4345     {
4346       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4347       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4348       if(cm.isQuadratic())
4349         {
4350           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4351           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4352           if(!cml.isDynamic())
4353             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4354           else
4355             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4356         }
4357     }
4358   if(delta==0)
4359     return ;
4360   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4361   const int *icptr(_nodal_connec->begin());
4362   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
4363   newConnI->alloc(nbOfCells+1,1);
4364   int *ocptr(newConn->getPointer()),*ociptr(newConnI->getPointer());
4365   *ociptr=0;
4366   _types.clear();
4367   for(int i=0;i<nbOfCells;i++,ociptr++)
4368     {
4369       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4370       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4371       if(!cm.isQuadratic())
4372         {
4373           _types.insert(type);
4374           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4375           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4376         }
4377       else
4378         {
4379           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4380           _types.insert(typel);
4381           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4382           int newNbOfNodes=cml.getNumberOfNodes();
4383           if(cml.isDynamic())
4384             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4385           *ocptr++=(int)typel;
4386           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4387           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4388         }
4389     }
4390   setConnectivity(newConn,newConnI,false);
4391 }
4392
4393 /*!
4394  * This method converts all linear cell in \a this to quadratic one.
4395  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4396  * 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)
4397  * 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.
4398  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4399  * end of the existing coordinates.
4400  * 
4401  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4402  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4403  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4404  * 
4405  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4406  *
4407  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4408  */
4409 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4410 {
4411   DataArrayInt *conn=0,*connI=0;
4412   DataArrayDouble *coords=0;
4413   std::set<INTERP_KERNEL::NormalizedCellType> types;
4414   checkFullyDefined();
4415   MCAuto<DataArrayInt> ret,connSafe,connISafe;
4416   MCAuto<DataArrayDouble> coordsSafe;
4417   int meshDim=getMeshDimension();
4418   switch(conversionType)
4419   {
4420     case 0:
4421       switch(meshDim)
4422       {
4423         case 1:
4424           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4425           connSafe=conn; connISafe=connI; coordsSafe=coords;
4426           break;
4427         case 2:
4428           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4429           connSafe=conn; connISafe=connI; coordsSafe=coords;
4430           break;
4431         case 3:
4432           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4433           connSafe=conn; connISafe=connI; coordsSafe=coords;
4434           break;
4435         default:
4436           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4437       }
4438       break;
4439         case 1:
4440           {
4441             switch(meshDim)
4442             {
4443               case 1:
4444                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4445                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4446                 break;
4447               case 2:
4448                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4449                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4450                 break;
4451               case 3:
4452                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4453                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4454                 break;
4455               default:
4456                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4457             }
4458             break;
4459           }
4460         default:
4461           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4462   }
4463   setConnectivity(connSafe,connISafe,false);
4464   _types=types;
4465   setCoords(coordsSafe);
4466   return ret.retn();
4467 }
4468
4469 /*!
4470  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
4471  * so that the number of cells remains the same. Quadratic faces are converted to
4472  * polygons. This method works only for 2D meshes in
4473  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
4474  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
4475  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4476  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
4477  *         a polylinized edge constituting the input polygon.
4478  *  \throw If the coordinates array is not set.
4479  *  \throw If the nodal connectivity of cells is not defined.
4480  *  \throw If \a this->getMeshDimension() != 2.
4481  *  \throw If \a this->getSpaceDimension() != 2.
4482  */
4483 void MEDCouplingUMesh::tessellate2D(double eps)
4484 {
4485   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
4486   if(spaceDim!=2)
4487     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
4488   switch(meshDim)
4489     {
4490     case 1:
4491       return tessellate2DCurveInternal(eps);
4492     case 2:
4493       return tessellate2DInternal(eps);
4494     default:
4495       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
4496     }
4497 }
4498 /*!
4499  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
4500  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4501  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
4502  *         a sub-divided edge.
4503  *  \throw If the coordinates array is not set.
4504  *  \throw If the nodal connectivity of cells is not defined.
4505  *  \throw If \a this->getMeshDimension() != 1.
4506  *  \throw If \a this->getSpaceDimension() != 2.
4507  */
4508
4509 #if 0
4510 /*!
4511  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
4512  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
4513  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
4514  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
4515  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
4516  * This method can be seen as the opposite method of colinearize2D.
4517  * 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
4518  * to avoid to modify the numbering of existing nodes.
4519  *
4520  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
4521  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
4522  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
4523  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
4524  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
4525  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
4526  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
4527  *
4528  * \sa buildDescendingConnectivity2
4529  */
4530 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
4531                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
4532 {
4533   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
4534     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
4535   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
4536   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
4537     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
4538   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
4539     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
4540   //DataArrayInt *out0(0),*outi0(0);
4541   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
4542   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
4543   //out0s=out0s->buildUnique(); out0s->sort(true);
4544 }
4545 #endif
4546
4547
4548 /*!
4549  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
4550  * In addition, returns an array mapping new cells to old ones. <br>
4551  * This method typically increases the number of cells in \a this mesh
4552  * but the number of nodes remains \b unchanged.
4553  * That's why the 3D splitting policies
4554  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
4555  *  \param [in] policy - specifies a pattern used for splitting.
4556  * The semantic of \a policy is:
4557  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
4558  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
4559  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4560  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4561  *
4562  *
4563  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
4564  *          an id of old cell producing it. The caller is to delete this array using
4565  *         decrRef() as it is no more needed.
4566  *
4567  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
4568  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
4569  *          and \a this->getMeshDimension() != 3. 
4570  *  \throw If \a policy is not one of the four discussed above.
4571  *  \throw If the nodal connectivity of cells is not defined.
4572  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
4573  */
4574 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
4575 {
4576   switch(policy)
4577   {
4578     case 0:
4579       return simplexizePol0();
4580     case 1:
4581       return simplexizePol1();
4582     case (int) INTERP_KERNEL::PLANAR_FACE_5:
4583         return simplexizePlanarFace5();
4584     case (int) INTERP_KERNEL::PLANAR_FACE_6:
4585         return simplexizePlanarFace6();
4586     default:
4587       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)");
4588   }
4589 }
4590
4591 /*!
4592  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
4593  * - 1D: INTERP_KERNEL::NORM_SEG2
4594  * - 2D: INTERP_KERNEL::NORM_TRI3
4595  * - 3D: INTERP_KERNEL::NORM_TETRA4.
4596  *
4597  * This method is useful for users that need to use P1 field services as
4598  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
4599  * All these methods need mesh support containing only simplex cells.
4600  *  \return bool - \c true if there are only simplex cells in \a this mesh.
4601  *  \throw If the coordinates array is not set.
4602  *  \throw If the nodal connectivity of cells is not defined.
4603  *  \throw If \a this->getMeshDimension() < 1.
4604  */
4605 bool MEDCouplingUMesh::areOnlySimplexCells() const
4606 {
4607   checkFullyDefined();
4608   int mdim=getMeshDimension();
4609   if(mdim<1 || mdim>3)
4610     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
4611   int nbCells=getNumberOfCells();
4612   const int *conn=_nodal_connec->begin();
4613   const int *connI=_nodal_connec_index->begin();
4614   for(int i=0;i<nbCells;i++)
4615     {
4616       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4617       if(!cm.isSimplex())
4618         return false;
4619     }
4620   return true;
4621 }
4622
4623
4624
4625 /*!
4626  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
4627  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
4628  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
4629  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
4630  * so it can be useful to call mergeNodes() before calling this method.
4631  *  \throw If \a this->getMeshDimension() <= 1.
4632  *  \throw If the coordinates array is not set.
4633  *  \throw If the nodal connectivity of cells is not defined.
4634  */
4635 void MEDCouplingUMesh::convertDegeneratedCells()
4636 {
4637   checkFullyDefined();
4638   if(getMeshDimension()<=1)
4639     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4640   int nbOfCells=getNumberOfCells();
4641   if(nbOfCells<1)
4642     return ;
4643   int initMeshLgth=getNodalConnectivityArrayLen();
4644   int *conn=_nodal_connec->getPointer();
4645   int *index=_nodal_connec_index->getPointer();
4646   int posOfCurCell=0;
4647   int newPos=0;
4648   int lgthOfCurCell;
4649   for(int i=0;i<nbOfCells;i++)
4650     {
4651       lgthOfCurCell=index[i+1]-posOfCurCell;
4652       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4653       int newLgth;
4654       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4655                                                                                                      conn+newPos+1,newLgth);
4656       conn[newPos]=newType;
4657       newPos+=newLgth+1;
4658       posOfCurCell=index[i+1];
4659       index[i+1]=newPos;
4660     }
4661   if(newPos!=initMeshLgth)
4662     _nodal_connec->reAlloc(newPos);
4663   computeTypes();
4664 }
4665
4666 /*!
4667  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
4668  * A cell is considered to be oriented correctly if an angle between its
4669  * normal vector and a given vector is less than \c PI / \c 2.
4670  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4671  *         cells. 
4672  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4673  *         checked.
4674  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4675  *         is not cleared before filling in.
4676  *  \throw If \a this->getMeshDimension() != 2.
4677  *  \throw If \a this->getSpaceDimension() != 3.
4678  *
4679  *  \if ENABLE_EXAMPLES
4680  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4681  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4682  *  \endif
4683  */
4684 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
4685 {
4686   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4687     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4688   int nbOfCells=getNumberOfCells();
4689   const int *conn=_nodal_connec->begin();
4690   const int *connI=_nodal_connec_index->begin();
4691   const double *coordsPtr=_coords->begin();
4692   for(int i=0;i<nbOfCells;i++)
4693     {
4694       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4695       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4696         {
4697           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4698           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4699             cells.push_back(i);
4700         }
4701     }
4702 }
4703
4704 /*!
4705  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
4706  * considered to be oriented correctly if an angle between its normal vector and a
4707  * given vector is less than \c PI / \c 2. 
4708  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4709  *         cells. 
4710  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4711  *         checked.
4712  *  \throw If \a this->getMeshDimension() != 2.
4713  *  \throw If \a this->getSpaceDimension() != 3.
4714  *
4715  *  \if ENABLE_EXAMPLES
4716  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4717  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4718  *  \endif
4719  *
4720  *  \sa changeOrientationOfCells
4721  */
4722 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
4723 {
4724   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4725     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
4726   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4727   const int *connI(_nodal_connec_index->begin());
4728   const double *coordsPtr(_coords->begin());
4729   bool isModified(false);
4730   for(int i=0;i<nbOfCells;i++)
4731     {
4732       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4733       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4734         {
4735           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4736           bool isQuadratic(cm.isQuadratic());
4737           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4738             {
4739               isModified=true;
4740               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4741             }
4742         }
4743     }
4744   if(isModified)
4745     _nodal_connec->declareAsNew();
4746   updateTime();
4747 }
4748
4749 /*!
4750  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
4751  *
4752  * \sa orientCorrectly2DCells
4753  */
4754 void MEDCouplingUMesh::changeOrientationOfCells()
4755 {
4756   int mdim(getMeshDimension());
4757   if(mdim!=2 && mdim!=1)
4758     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
4759   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4760   const int *connI(_nodal_connec_index->begin());
4761   if(mdim==2)
4762     {//2D
4763       for(int i=0;i<nbOfCells;i++)
4764         {
4765           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4766           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4767           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4768         }
4769     }
4770   else
4771     {//1D
4772       for(int i=0;i<nbOfCells;i++)
4773         {
4774           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4775           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4776           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4777         }
4778     }
4779 }
4780
4781 /*!
4782  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
4783  * oriented facets. The normal vector of the facet should point out of the cell.
4784  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4785  *         is not cleared before filling in.
4786  *  \throw If \a this->getMeshDimension() != 3.
4787  *  \throw If \a this->getSpaceDimension() != 3.
4788  *  \throw If the coordinates array is not set.
4789  *  \throw If the nodal connectivity of cells is not defined.
4790  *
4791  *  \if ENABLE_EXAMPLES
4792  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4793  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4794  *  \endif
4795  */
4796 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
4797 {
4798   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4799     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
4800   int nbOfCells=getNumberOfCells();
4801   const int *conn=_nodal_connec->begin();
4802   const int *connI=_nodal_connec_index->begin();
4803   const double *coordsPtr=_coords->begin();
4804   for(int i=0;i<nbOfCells;i++)
4805     {
4806       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4807       if(type==INTERP_KERNEL::NORM_POLYHED)
4808         {
4809           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4810             cells.push_back(i);
4811         }
4812     }
4813 }
4814
4815 /*!
4816  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
4817  * out of the cell. 
4818  *  \throw If \a this->getMeshDimension() != 3.
4819  *  \throw If \a this->getSpaceDimension() != 3.
4820  *  \throw If the coordinates array is not set.
4821  *  \throw If the nodal connectivity of cells is not defined.
4822  *  \throw If the reparation fails.
4823  *
4824  *  \if ENABLE_EXAMPLES
4825  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4826  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4827  *  \endif
4828  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4829  */
4830 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
4831 {
4832   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4833     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
4834   int nbOfCells=getNumberOfCells();
4835   int *conn=_nodal_connec->getPointer();
4836   const int *connI=_nodal_connec_index->begin();
4837   const double *coordsPtr=_coords->begin();
4838   for(int i=0;i<nbOfCells;i++)
4839     {
4840       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4841       if(type==INTERP_KERNEL::NORM_POLYHED)
4842         {
4843           try
4844           {
4845               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4846                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4847           }
4848           catch(INTERP_KERNEL::Exception& e)
4849           {
4850               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
4851               throw INTERP_KERNEL::Exception(oss.str());
4852           }
4853         }
4854     }
4855   updateTime();
4856 }
4857
4858 /*!
4859  * This method invert orientation of all cells in \a this. 
4860  * After calling this method the absolute value of measure of cells in \a this are the same than before calling.
4861  * This method only operates on the connectivity so coordinates are not touched at all.
4862  */
4863 void MEDCouplingUMesh::invertOrientationOfAllCells()
4864 {
4865   checkConnectivityFullyDefined();
4866   std::set<INTERP_KERNEL::NormalizedCellType> gts(getAllGeoTypes());
4867   int *conn(_nodal_connec->getPointer());
4868   const int *conni(_nodal_connec_index->begin());
4869   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator gt=gts.begin();gt!=gts.end();gt++)
4870     {
4871       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::OrientationInverter> oi(INTERP_KERNEL::OrientationInverter::BuildInstanceFrom(*gt));
4872       MCAuto<DataArrayInt> cwt(giveCellsWithType(*gt));
4873       for(const int *it=cwt->begin();it!=cwt->end();it++)
4874         oi->operate(conn+conni[*it]+1,conn+conni[*it+1]);
4875     }
4876   updateTime();
4877 }
4878
4879 /*!
4880  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
4881  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
4882  * according to which the first facet of the cell should be oriented to have the normal vector
4883  * pointing out of cell.
4884  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
4885  *         cells. The caller is to delete this array using decrRef() as it is no more
4886  *         needed. 
4887  *  \throw If \a this->getMeshDimension() != 3.
4888  *  \throw If \a this->getSpaceDimension() != 3.
4889  *  \throw If the coordinates array is not set.
4890  *  \throw If the nodal connectivity of cells is not defined.
4891  *
4892  *  \if ENABLE_EXAMPLES
4893  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
4894  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
4895  *  \endif
4896  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4897  */
4898 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
4899 {
4900   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
4901   if(getMeshDimension()!=3)
4902     throw INTERP_KERNEL::Exception(msg);
4903   int spaceDim=getSpaceDimension();
4904   if(spaceDim!=3)
4905     throw INTERP_KERNEL::Exception(msg);
4906   //
4907   int nbOfCells=getNumberOfCells();
4908   int *conn=_nodal_connec->getPointer();
4909   const int *connI=_nodal_connec_index->begin();
4910   const double *coo=getCoords()->begin();
4911   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
4912   for(int i=0;i<nbOfCells;i++)
4913     {
4914       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4915       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
4916         {
4917           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
4918             {
4919               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4920               cells->pushBackSilent(i);
4921             }
4922         }
4923     }
4924   return cells.retn();
4925 }
4926
4927 /*!
4928  * This method is a faster method to correct orientation of all 3D cells in \a this.
4929  * 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.
4930  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
4931  * 
4932  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
4933  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
4934  */
4935 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
4936 {
4937   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4938     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
4939   int nbOfCells=getNumberOfCells();
4940   int *conn=_nodal_connec->getPointer();
4941   const int *connI=_nodal_connec_index->begin();
4942   const double *coordsPtr=_coords->begin();
4943   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4944   for(int i=0;i<nbOfCells;i++)
4945     {
4946       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4947       switch(type)
4948       {
4949         case INTERP_KERNEL::NORM_TETRA4:
4950           {
4951             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4952               {
4953                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
4954                 ret->pushBackSilent(i);
4955               }
4956             break;
4957           }
4958         case INTERP_KERNEL::NORM_PYRA5:
4959           {
4960             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4961               {
4962                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
4963                 ret->pushBackSilent(i);
4964               }
4965             break;
4966           }
4967         case INTERP_KERNEL::NORM_PENTA6:
4968         case INTERP_KERNEL::NORM_HEXA8:
4969         case INTERP_KERNEL::NORM_HEXGP12:
4970           {
4971             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4972               {
4973                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4974                 ret->pushBackSilent(i);
4975               }
4976             break;
4977           }
4978         case INTERP_KERNEL::NORM_POLYHED:
4979           {
4980             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4981               {
4982                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4983                 ret->pushBackSilent(i);
4984               }
4985             break;
4986           }
4987         default:
4988           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 !");
4989       }
4990     }
4991   updateTime();
4992   return ret.retn();
4993 }
4994
4995 /*!
4996  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
4997  * If it is not the case an exception will be thrown.
4998  * This method is fast because the first cell of \a this is used to compute the plane.
4999  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5000  * \param pos output of size at least 3 used to store a point owned of searched plane.
5001  */
5002 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5003 {
5004   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5005     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5006   const int *conn=_nodal_connec->begin();
5007   const int *connI=_nodal_connec_index->begin();
5008   const double *coordsPtr=_coords->begin();
5009   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5010   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5011 }
5012
5013 /*!
5014  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5015  * cells. Currently cells of the following types are treated:
5016  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5017  * For a cell of other type an exception is thrown.
5018  * Space dimension of a 2D mesh can be either 2 or 3.
5019  * The Edge Ratio of a cell \f$t\f$ is: 
5020  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5021  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5022  *  the smallest edge lengths of \f$t\f$.
5023  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5024  *          cells and one time, lying on \a this mesh. The caller is to delete this
5025  *          field using decrRef() as it is no more needed. 
5026  *  \throw If the coordinates array is not set.
5027  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5028  *  \throw If the connectivity data array has more than one component.
5029  *  \throw If the connectivity data array has a named component.
5030  *  \throw If the connectivity index data array has more than one component.
5031  *  \throw If the connectivity index data array has a named component.
5032  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5033  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5034  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5035  */
5036 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
5037 {
5038   checkConsistencyLight();
5039   int spaceDim=getSpaceDimension();
5040   int meshDim=getMeshDimension();
5041   if(spaceDim!=2 && spaceDim!=3)
5042     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5043   if(meshDim!=2 && meshDim!=3)
5044     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5045   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5046   ret->setMesh(this);
5047   int nbOfCells=getNumberOfCells();
5048   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5049   arr->alloc(nbOfCells,1);
5050   double *pt=arr->getPointer();
5051   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5052   const int *conn=_nodal_connec->begin();
5053   const int *connI=_nodal_connec_index->begin();
5054   const double *coo=_coords->begin();
5055   double tmp[12];
5056   for(int i=0;i<nbOfCells;i++,pt++)
5057     {
5058       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5059       switch(t)
5060       {
5061         case INTERP_KERNEL::NORM_TRI3:
5062           {
5063             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5064             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5065             break;
5066           }
5067         case INTERP_KERNEL::NORM_QUAD4:
5068           {
5069             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5070             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5071             break;
5072           }
5073         case INTERP_KERNEL::NORM_TETRA4:
5074           {
5075             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5076             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5077             break;
5078           }
5079         default:
5080           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5081       }
5082       conn+=connI[i+1]-connI[i];
5083     }
5084   ret->setName("EdgeRatio");
5085   ret->synchronizeTimeWithSupport();
5086   return ret.retn();
5087 }
5088
5089 /*!
5090  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5091  * cells. Currently cells of the following types are treated:
5092  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5093  * For a cell of other type an exception is thrown.
5094  * Space dimension of a 2D mesh can be either 2 or 3.
5095  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5096  *          cells and one time, lying on \a this mesh. The caller is to delete this
5097  *          field using decrRef() as it is no more needed. 
5098  *  \throw If the coordinates array is not set.
5099  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5100  *  \throw If the connectivity data array has more than one component.
5101  *  \throw If the connectivity data array has a named component.
5102  *  \throw If the connectivity index data array has more than one component.
5103  *  \throw If the connectivity index data array has a named component.
5104  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5105  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5106  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5107  */
5108 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
5109 {
5110   checkConsistencyLight();
5111   int spaceDim=getSpaceDimension();
5112   int meshDim=getMeshDimension();
5113   if(spaceDim!=2 && spaceDim!=3)
5114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5115   if(meshDim!=2 && meshDim!=3)
5116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5117   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5118   ret->setMesh(this);
5119   int nbOfCells=getNumberOfCells();
5120   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5121   arr->alloc(nbOfCells,1);
5122   double *pt=arr->getPointer();
5123   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5124   const int *conn=_nodal_connec->begin();
5125   const int *connI=_nodal_connec_index->begin();
5126   const double *coo=_coords->begin();
5127   double tmp[12];
5128   for(int i=0;i<nbOfCells;i++,pt++)
5129     {
5130       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5131       switch(t)
5132       {
5133         case INTERP_KERNEL::NORM_TRI3:
5134           {
5135             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5136             *pt=INTERP_KERNEL::triAspectRatio(tmp);
5137             break;
5138           }
5139         case INTERP_KERNEL::NORM_QUAD4:
5140           {
5141             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5142             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5143             break;
5144           }
5145         case INTERP_KERNEL::NORM_TETRA4:
5146           {
5147             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5148             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5149             break;
5150           }
5151         default:
5152           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5153       }
5154       conn+=connI[i+1]-connI[i];
5155     }
5156   ret->setName("AspectRatio");
5157   ret->synchronizeTimeWithSupport();
5158   return ret.retn();
5159 }
5160
5161 /*!
5162  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
5163  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
5164  * in 3D space. Currently only cells of the following types are
5165  * treated: INTERP_KERNEL::NORM_QUAD4.
5166  * For a cell of other type an exception is thrown.
5167  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
5168  * Defining
5169  * \f$t=\vec{da}\times\vec{ab}\f$,
5170  * \f$u=\vec{ab}\times\vec{bc}\f$
5171  * \f$v=\vec{bc}\times\vec{cd}\f$
5172  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
5173  *  \f[
5174  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
5175  *  \f]
5176  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5177  *          cells and one time, lying on \a this mesh. The caller is to delete this
5178  *          field using decrRef() as it is no more needed. 
5179  *  \throw If the coordinates array is not set.
5180  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5181  *  \throw If the connectivity data array has more than one component.
5182  *  \throw If the connectivity data array has a named component.
5183  *  \throw If the connectivity index data array has more than one component.
5184  *  \throw If the connectivity index data array has a named component.
5185  *  \throw If \a this->getMeshDimension() != 2.
5186  *  \throw If \a this->getSpaceDimension() != 3.
5187  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5188  */
5189 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
5190 {
5191   checkConsistencyLight();
5192   int spaceDim=getSpaceDimension();
5193   int meshDim=getMeshDimension();
5194   if(spaceDim!=3)
5195     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5196   if(meshDim!=2)
5197     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5198   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5199   ret->setMesh(this);
5200   int nbOfCells=getNumberOfCells();
5201   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5202   arr->alloc(nbOfCells,1);
5203   double *pt=arr->getPointer();
5204   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5205   const int *conn=_nodal_connec->begin();
5206   const int *connI=_nodal_connec_index->begin();
5207   const double *coo=_coords->begin();
5208   double tmp[12];
5209   for(int i=0;i<nbOfCells;i++,pt++)
5210     {
5211       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5212       switch(t)
5213       {
5214         case INTERP_KERNEL::NORM_QUAD4:
5215           {
5216             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5217             *pt=INTERP_KERNEL::quadWarp(tmp);
5218             break;
5219           }
5220         default:
5221           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5222       }
5223       conn+=connI[i+1]-connI[i];
5224     }
5225   ret->setName("Warp");
5226   ret->synchronizeTimeWithSupport();
5227   return ret.retn();
5228 }
5229
5230
5231 /*!
5232  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
5233  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
5234  * treated: INTERP_KERNEL::NORM_QUAD4.
5235  * The skew is computed as follow for a quad with points (a,b,c,d): let
5236  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
5237  * then the skew is computed as:
5238  *  \f[
5239  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
5240  *  \f]
5241  *
5242  * For a cell of other type an exception is thrown.
5243  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5244  *          cells and one time, lying on \a this mesh. The caller is to delete this
5245  *          field using decrRef() as it is no more needed. 
5246  *  \throw If the coordinates array is not set.
5247  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5248  *  \throw If the connectivity data array has more than one component.
5249  *  \throw If the connectivity data array has a named component.
5250  *  \throw If the connectivity index data array has more than one component.
5251  *  \throw If the connectivity index data array has a named component.
5252  *  \throw If \a this->getMeshDimension() != 2.
5253  *  \throw If \a this->getSpaceDimension() != 3.
5254  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5255  */
5256 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
5257 {
5258   checkConsistencyLight();
5259   int spaceDim=getSpaceDimension();
5260   int meshDim=getMeshDimension();
5261   if(spaceDim!=3)
5262     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5263   if(meshDim!=2)
5264     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5265   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5266   ret->setMesh(this);
5267   int nbOfCells=getNumberOfCells();
5268   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5269   arr->alloc(nbOfCells,1);
5270   double *pt=arr->getPointer();
5271   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5272   const int *conn=_nodal_connec->begin();
5273   const int *connI=_nodal_connec_index->begin();
5274   const double *coo=_coords->begin();
5275   double tmp[12];
5276   for(int i=0;i<nbOfCells;i++,pt++)
5277     {
5278       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5279       switch(t)
5280       {
5281         case INTERP_KERNEL::NORM_QUAD4:
5282           {
5283             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5284             *pt=INTERP_KERNEL::quadSkew(tmp);
5285             break;
5286           }
5287         default:
5288           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5289       }
5290       conn+=connI[i+1]-connI[i];
5291     }
5292   ret->setName("Skew");
5293   ret->synchronizeTimeWithSupport();
5294   return ret.retn();
5295 }
5296
5297 /*!
5298  * 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.
5299  *
5300  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
5301  *
5302  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
5303  */
5304 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
5305 {
5306   checkConsistencyLight();
5307   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
5308   ret->setMesh(this);
5309   std::set<INTERP_KERNEL::NormalizedCellType> types;
5310   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
5311   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
5312   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
5313   arr->alloc(nbCells,1);
5314   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
5315     {
5316       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
5317       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
5318       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
5319     }
5320   ret->setArray(arr);
5321   ret->setName("Diameter");
5322   return ret.retn();
5323 }
5324
5325 /*!
5326  * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax).
5327  * 
5328  * \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)
5329  *                         For all other cases this input parameter is ignored.
5330  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5331  * 
5332  * \throw If \a this is not fully set (coordinates and connectivity).
5333  * \throw If a cell in \a this has no valid nodeId.
5334  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5335  */
5336 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
5337 {
5338   int mDim(getMeshDimension()),sDim(getSpaceDimension());
5339   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.
5340     return getBoundingBoxForBBTreeFast();
5341   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
5342     {
5343       bool presenceOfQuadratic(false);
5344       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
5345         {
5346           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
5347           if(cm.isQuadratic())
5348             presenceOfQuadratic=true;
5349         }
5350       if(!presenceOfQuadratic)
5351         return getBoundingBoxForBBTreeFast();
5352       if(mDim==2 && sDim==2)
5353         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
5354       else
5355         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
5356     }
5357   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) !");
5358 }
5359
5360 /*!
5361  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
5362  * So meshes having quadratic cells the computed bounding boxes can be invalid !
5363  * 
5364  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5365  * 
5366  * \throw If \a this is not fully set (coordinates and connectivity).
5367  * \throw If a cell in \a this has no valid nodeId.
5368  */
5369 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
5370 {
5371   checkFullyDefined();
5372   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
5373   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5374   double *bbox(ret->getPointer());
5375   for(int i=0;i<nbOfCells*spaceDim;i++)
5376     {
5377       bbox[2*i]=std::numeric_limits<double>::max();
5378       bbox[2*i+1]=-std::numeric_limits<double>::max();
5379     }
5380   const double *coordsPtr(_coords->begin());
5381   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5382   for(int i=0;i<nbOfCells;i++)
5383     {
5384       int offset=connI[i]+1;
5385       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
5386       for(int j=0;j<nbOfNodesForCell;j++)
5387         {
5388           int nodeId=conn[offset+j];
5389           if(nodeId>=0 && nodeId<nbOfNodes)
5390             {
5391               for(int k=0;k<spaceDim;k++)
5392                 {
5393                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5394                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5395                 }
5396               kk++;
5397             }
5398         }
5399       if(kk==0)
5400         {
5401           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
5402           throw INTERP_KERNEL::Exception(oss.str());
5403         }
5404     }
5405   return ret.retn();
5406 }
5407
5408 /*!
5409  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
5410  * useful for 2D meshes having quadratic cells
5411  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5412  * the two extremities of the arc of circle).
5413  * 
5414  * \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)
5415  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5416  * \throw If \a this is not fully defined.
5417  * \throw If \a this is not a mesh with meshDimension equal to 2.
5418  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5419  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
5420  */
5421 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
5422 {
5423   checkFullyDefined();
5424   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5425   if(spaceDim!=2 || mDim!=2)
5426     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!");
5427   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5428   double *bbox(ret->getPointer());
5429   const double *coords(_coords->begin());
5430   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5431   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5432     {
5433       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5434       int sz(connI[1]-connI[0]-1);
5435       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
5436       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5437       INTERP_KERNEL::QuadraticPolygon *pol(0);
5438       for(int j=0;j<sz;j++)
5439         {
5440           int nodeId(conn[*connI+1+j]);
5441           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5442         }
5443       if(!cm.isQuadratic())
5444         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
5445       else
5446         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
5447       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
5448       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
5449     }
5450   return ret.retn();
5451 }
5452
5453 /*!
5454  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
5455  * useful for 2D meshes having quadratic cells
5456  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5457  * the two extremities of the arc of circle).
5458  * 
5459  * \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)
5460  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5461  * \throw If \a this is not fully defined.
5462  * \throw If \a this is not a mesh with meshDimension equal to 1.
5463  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5464  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5465  */
5466 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
5467 {
5468   checkFullyDefined();
5469   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5470   if(spaceDim!=2 || mDim!=1)
5471     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!");
5472   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5473   double *bbox(ret->getPointer());
5474   const double *coords(_coords->begin());
5475   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5476   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5477     {
5478       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5479       int sz(connI[1]-connI[0]-1);
5480       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
5481       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5482       INTERP_KERNEL::Edge *edge(0);
5483       for(int j=0;j<sz;j++)
5484         {
5485           int nodeId(conn[*connI+1+j]);
5486           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5487         }
5488       if(!cm.isQuadratic())
5489         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
5490       else
5491         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
5492       const INTERP_KERNEL::Bounds& b(edge->getBounds());
5493       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
5494     }
5495   return ret.retn();
5496 }
5497
5498 /// @cond INTERNAL
5499
5500 namespace MEDCouplingImpl
5501 {
5502   class ConnReader
5503   {
5504   public:
5505     ConnReader(const int *c, int val):_conn(c),_val(val) { }
5506     bool operator() (const int& pos) { return _conn[pos]!=_val; }
5507   private:
5508     const int *_conn;
5509     int _val;
5510   };
5511
5512   class ConnReader2
5513   {
5514   public:
5515     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5516     bool operator() (const int& pos) { return _conn[pos]==_val; }
5517   private:
5518     const int *_conn;
5519     int _val;
5520   };
5521 }
5522
5523 /// @endcond
5524
5525 /*!
5526  * This method expects that \a this is sorted by types. If not an exception will be thrown.
5527  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5528  * \a this is composed in cell types.
5529  * The returned array is of size 3*n where n is the number of different types present in \a this. 
5530  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
5531  * This parameter is kept only for compatibility with other methode listed above.
5532  */
5533 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
5534 {
5535   checkConnectivityFullyDefined();
5536   const int *conn=_nodal_connec->begin();
5537   const int *connI=_nodal_connec_index->begin();
5538   const int *work=connI;
5539   int nbOfCells=getNumberOfCells();
5540   std::size_t n=getAllGeoTypes().size();
5541   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
5542   std::set<INTERP_KERNEL::NormalizedCellType> types;
5543   for(std::size_t i=0;work!=connI+nbOfCells;i++)
5544     {
5545       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5546       if(types.find(typ)!=types.end())
5547         {
5548           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5549           oss << " is not contiguous !";
5550           throw INTERP_KERNEL::Exception(oss.str());
5551         }
5552       types.insert(typ);
5553       ret[3*i]=typ;
5554       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
5555       ret[3*i+1]=(int)std::distance(work,work2);
5556       work=work2;
5557     }
5558   return ret;
5559 }
5560
5561 /*!
5562  * This method is used to check that this has contiguous cell type in same order than described in \a code.
5563  * only for types cell, type node is not managed.
5564  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
5565  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5566  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5567  * If 2 or more same geometric type is in \a code and exception is thrown too.
5568  *
5569  * This method firstly checks
5570  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5571  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5572  * an exception is thrown too.
5573  * 
5574  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
5575  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
5576  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5577  */
5578 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
5579 {
5580   if(code.empty())
5581     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5582   std::size_t sz=code.size();
5583   std::size_t n=sz/3;
5584   if(sz%3!=0)
5585     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5586   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5587   int nb=0;
5588   bool isNoPflUsed=true;
5589   for(std::size_t i=0;i<n;i++)
5590     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5591       {
5592         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5593         nb+=code[3*i+1];
5594         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5595           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5596         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
5597       }
5598   if(types.size()!=n)
5599     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5600   if(isNoPflUsed)
5601     {
5602       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5603         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5604       if(types.size()==_types.size())
5605         return 0;
5606     }
5607   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5608   ret->alloc(nb,1);
5609   int *retPtr=ret->getPointer();
5610   const int *connI=_nodal_connec_index->begin();
5611   const int *conn=_nodal_connec->begin();
5612   int nbOfCells=getNumberOfCells();
5613   const int *i=connI;
5614   int kk=0;
5615   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5616     {
5617       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
5618       int offset=(int)std::distance(connI,i);
5619       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
5620       int nbOfCellsOfCurType=(int)std::distance(i,j);
5621       if(code[3*kk+2]==-1)
5622         for(int k=0;k<nbOfCellsOfCurType;k++)
5623           *retPtr++=k+offset;
5624       else
5625         {
5626           int idInIdsPerType=code[3*kk+2];
5627           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
5628             {
5629               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
5630               if(zePfl)
5631                 {
5632                   zePfl->checkAllocated();
5633                   if(zePfl->getNumberOfComponents()==1)
5634                     {
5635                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
5636                         {
5637                           if(*k>=0 && *k<nbOfCellsOfCurType)
5638                             *retPtr=(*k)+offset;
5639                           else
5640                             {
5641                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
5642                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
5643                               throw INTERP_KERNEL::Exception(oss.str());
5644                             }
5645                         }
5646                     }
5647                   else
5648                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
5649                 }
5650               else
5651                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
5652             }
5653           else
5654             {
5655               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
5656               oss << " should be in [0," << idsPerType.size() << ") !";
5657               throw INTERP_KERNEL::Exception(oss.str());
5658             }
5659         }
5660       i=j;
5661     }
5662   return ret.retn();
5663 }
5664
5665 /*!
5666  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
5667  * 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.
5668  * 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.
5669  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
5670  * 
5671  * \param [in] profile
5672  * \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.
5673  * \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,
5674  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5675  * \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.
5676  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5677  * \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
5678  */
5679 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
5680 {
5681   if(!profile)
5682     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
5683   if(profile->getNumberOfComponents()!=1)
5684     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5685   checkConnectivityFullyDefined();
5686   const int *conn=_nodal_connec->begin();
5687   const int *connI=_nodal_connec_index->begin();
5688   int nbOfCells=getNumberOfCells();
5689   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5690   std::vector<int> typeRangeVals(1);
5691   for(const int *i=connI;i!=connI+nbOfCells;)
5692     {
5693       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5694       if(std::find(types.begin(),types.end(),curType)!=types.end())
5695         {
5696           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5697         }
5698       types.push_back(curType);
5699       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5700       typeRangeVals.push_back((int)std::distance(connI,i));
5701     }
5702   //
5703   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5704   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5705   MCAuto<DataArrayInt> tmp0=castArr;
5706   MCAuto<DataArrayInt> tmp1=rankInsideCast;
5707   MCAuto<DataArrayInt> tmp2=castsPresent;
5708   //
5709   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5710   code.resize(3*nbOfCastsFinal);
5711   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
5712   std::vector< MCAuto<DataArrayInt> > idsPerType2;
5713   for(int i=0;i<nbOfCastsFinal;i++)
5714     {
5715       int castId=castsPresent->getIJ(i,0);
5716       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
5717       idsInPflPerType2.push_back(tmp3);
5718       code[3*i]=(int)types[castId];
5719       code[3*i+1]=tmp3->getNumberOfTuples();
5720       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->begin(),tmp3->begin()+tmp3->getNumberOfTuples());
5721       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
5722         {
5723           tmp4->copyStringInfoFrom(*profile);
5724           idsPerType2.push_back(tmp4);
5725           code[3*i+2]=(int)idsPerType2.size()-1;
5726         }
5727       else
5728         {
5729           code[3*i+2]=-1;
5730         }
5731     }
5732   std::size_t sz2=idsInPflPerType2.size();
5733   idsInPflPerType.resize(sz2);
5734   for(std::size_t i=0;i<sz2;i++)
5735     {
5736       DataArrayInt *locDa=idsInPflPerType2[i];
5737       locDa->incrRef();
5738       idsInPflPerType[i]=locDa;
5739     }
5740   std::size_t sz=idsPerType2.size();
5741   idsPerType.resize(sz);
5742   for(std::size_t i=0;i<sz;i++)
5743     {
5744       DataArrayInt *locDa=idsPerType2[i];
5745       locDa->incrRef();
5746       idsPerType[i]=locDa;
5747     }
5748 }
5749
5750 /*!
5751  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5752  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5753  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5754  * 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.
5755  */
5756 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
5757 {
5758   checkFullyDefined();
5759   nM1LevMesh->checkFullyDefined();
5760   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5761     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5762   if(_coords!=nM1LevMesh->getCoords())
5763     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5764   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
5765   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
5766   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5767   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5768   desc->transformWithIndArr(ret0->begin(),ret0->begin()+ret0->getNbOfElems());
5769   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5770   tmp->setConnectivity(tmp0,tmp1);
5771   tmp->renumberCells(ret0->begin(),false);
5772   revDesc=tmp->getNodalConnectivity();
5773   revDescIndx=tmp->getNodalConnectivityIndex();
5774   DataArrayInt *ret=0;
5775   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5776     {
5777       int tmp2;
5778       ret->getMaxValue(tmp2);
5779       ret->decrRef();
5780       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5781       throw INTERP_KERNEL::Exception(oss.str());
5782     }
5783   nM1LevMeshIds=ret;
5784   //
5785   revDesc->incrRef();
5786   revDescIndx->incrRef();
5787   ret1->incrRef();
5788   ret0->incrRef();
5789   meshnM1Old2New=ret0;
5790   return ret1;
5791 }
5792
5793 /*!
5794  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
5795  * necessary for writing the mesh to MED file. Additionally returns a permutation array
5796  * in "Old to New" mode.
5797  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
5798  *          this array using decrRef() as it is no more needed.
5799  *  \throw If the nodal connectivity of cells is not defined.
5800  */
5801 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
5802 {
5803   checkConnectivityFullyDefined();
5804   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
5805   renumberCells(ret->begin(),false);
5806   return ret.retn();
5807 }
5808
5809 /*!
5810  * This methods checks that cells are sorted by their types.
5811  * This method makes asumption (no check) that connectivity is correctly set before calling.
5812  */
5813 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5814 {
5815   checkFullyDefined();
5816   const int *conn=_nodal_connec->begin();
5817   const int *connI=_nodal_connec_index->begin();
5818   int nbOfCells=getNumberOfCells();
5819   std::set<INTERP_KERNEL::NormalizedCellType> types;
5820   for(const int *i=connI;i!=connI+nbOfCells;)
5821     {
5822       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5823       if(types.find(curType)!=types.end())
5824         return false;
5825       types.insert(curType);
5826       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5827     }
5828   return true;
5829 }
5830
5831 /*!
5832  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
5833  * The geometric type order is specified by MED file.
5834  * 
5835  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
5836  */
5837 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
5838 {
5839   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5840 }
5841
5842 /*!
5843  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5844  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
5845  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
5846  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
5847  */
5848 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5849 {
5850   checkFullyDefined();
5851   const int *conn=_nodal_connec->begin();
5852   const int *connI=_nodal_connec_index->begin();
5853   int nbOfCells=getNumberOfCells();
5854   if(nbOfCells==0)
5855     return true;
5856   int lastPos=-1;
5857   std::set<INTERP_KERNEL::NormalizedCellType> sg;
5858   for(const int *i=connI;i!=connI+nbOfCells;)
5859     {
5860       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5861       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
5862       if(isTypeExists!=orderEnd)
5863         {
5864           int pos=(int)std::distance(orderBg,isTypeExists);
5865           if(pos<=lastPos)
5866             return false;
5867           lastPos=pos;
5868           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5869         }
5870       else
5871         {
5872           if(sg.find(curType)==sg.end())
5873             {
5874               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5875               sg.insert(curType);
5876             }
5877           else
5878             return false;
5879         }
5880     }
5881   return true;
5882 }
5883
5884 /*!
5885  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5886  * 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
5887  * 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'.
5888  */
5889 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
5890 {
5891   checkConnectivityFullyDefined();
5892   int nbOfCells=getNumberOfCells();
5893   const int *conn=_nodal_connec->begin();
5894   const int *connI=_nodal_connec_index->begin();
5895   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
5896   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
5897   tmpa->alloc(nbOfCells,1);
5898   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
5899   tmpb->fillWithZero();
5900   int *tmp=tmpa->getPointer();
5901   int *tmp2=tmpb->getPointer();
5902   for(const int *i=connI;i!=connI+nbOfCells;i++)
5903     {
5904       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
5905       if(where!=orderEnd)
5906         {
5907           int pos=(int)std::distance(orderBg,where);
5908           tmp2[pos]++;
5909           tmp[std::distance(connI,i)]=pos;
5910         }
5911       else
5912         {
5913           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
5914           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
5915           oss << " has a type " << cm.getRepr() << " not in input array of type !";
5916           throw INTERP_KERNEL::Exception(oss.str());
5917         }
5918     }
5919   nbPerType=tmpb.retn();
5920   return tmpa.retn();
5921 }
5922
5923 /*!
5924  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
5925  *
5926  * \return a new object containing the old to new correspondance.
5927  *
5928  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5929  */
5930 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
5931 {
5932   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5933 }
5934
5935 /*!
5936  * 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.
5937  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
5938  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
5939  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
5940  */
5941 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5942 {
5943   DataArrayInt *nbPerType=0;
5944   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
5945   nbPerType->decrRef();
5946   return tmpa->buildPermArrPerLevel();
5947 }
5948
5949 /*!
5950  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
5951  * The number of cells remains unchanged after the call of this method.
5952  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
5953  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5954  *
5955  * \return the array giving the correspondance old to new.
5956  */
5957 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
5958 {
5959   checkFullyDefined();
5960   computeTypes();
5961   const int *conn=_nodal_connec->begin();
5962   const int *connI=_nodal_connec_index->begin();
5963   int nbOfCells=getNumberOfCells();
5964   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5965   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
5966     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
5967       {
5968         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5969         types.push_back(curType);
5970         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
5971       }
5972   DataArrayInt *ret=DataArrayInt::New();
5973   ret->alloc(nbOfCells,1);
5974   int *retPtr=ret->getPointer();
5975   std::fill(retPtr,retPtr+nbOfCells,-1);
5976   int newCellId=0;
5977   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5978     {
5979       for(const int *i=connI;i!=connI+nbOfCells;i++)
5980         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5981           retPtr[std::distance(connI,i)]=newCellId++;
5982     }
5983   renumberCells(retPtr,false);
5984   return ret;
5985 }
5986
5987 /*!
5988  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
5989  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
5990  * This method makes asumption that connectivity is correctly set before calling.
5991  */
5992 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
5993 {
5994   checkConnectivityFullyDefined();
5995   const int *conn=_nodal_connec->begin();
5996   const int *connI=_nodal_connec_index->begin();
5997   int nbOfCells=getNumberOfCells();
5998   std::vector<MEDCouplingUMesh *> ret;
5999   for(const int *i=connI;i!=connI+nbOfCells;)
6000     {
6001       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6002       int beginCellId=(int)std::distance(connI,i);
6003       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
6004       int endCellId=(int)std::distance(connI,i);
6005       int sz=endCellId-beginCellId;
6006       int *cells=new int[sz];
6007       for(int j=0;j<sz;j++)
6008         cells[j]=beginCellId+j;
6009       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6010       delete [] cells;
6011       ret.push_back(m);
6012     }
6013   return ret;
6014 }
6015
6016 /*!
6017  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6018  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6019  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6020  *
6021  * \return a newly allocated instance, that the caller must manage.
6022  * \throw If \a this contains more than one geometric type.
6023  * \throw If the nodal connectivity of \a this is not fully defined.
6024  * \throw If the internal data is not coherent.
6025  */
6026 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6027 {
6028   checkConnectivityFullyDefined();
6029   if(_types.size()!=1)
6030     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6031   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6032   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6033   ret->setCoords(getCoords());
6034   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6035   if(retC)
6036     {
6037       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6038       retC->setNodalConnectivity(c);
6039     }
6040   else
6041     {
6042       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6043       if(!retD)
6044         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6045       DataArrayInt *c=0,*ci=0;
6046       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6047       MCAuto<DataArrayInt> cs(c),cis(ci);
6048       retD->setNodalConnectivity(cs,cis);
6049     }
6050   return ret.retn();
6051 }
6052
6053 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6054 {
6055   checkConnectivityFullyDefined();
6056   if(_types.size()!=1)
6057     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6058   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6059   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6060   if(cm.isDynamic())
6061     {
6062       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6063       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6064       throw INTERP_KERNEL::Exception(oss.str());
6065     }
6066   int nbCells=getNumberOfCells();
6067   int typi=(int)typ;
6068   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6069   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6070   int *outPtr=connOut->getPointer();
6071   const int *conn=_nodal_connec->begin();
6072   const int *connI=_nodal_connec_index->begin();
6073   nbNodesPerCell++;
6074   for(int i=0;i<nbCells;i++,connI++)
6075     {
6076       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6077         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6078       else
6079         {
6080           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 << ") !";
6081           throw INTERP_KERNEL::Exception(oss.str());
6082         }
6083     }
6084   return connOut.retn();
6085 }
6086
6087 /*!
6088  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
6089  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
6090  * \param nodalConn
6091  * \param nodalConnI
6092  */
6093 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
6094 {
6095   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
6096   checkConnectivityFullyDefined();
6097   if(_types.size()!=1)
6098     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6099   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6100   if(lgth<nbCells)
6101     throw INTERP_KERNEL::Exception(msg0);
6102   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6103   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6104   int *cp(c->getPointer()),*cip(ci->getPointer());
6105   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6106   cip[0]=0;
6107   for(int i=0;i<nbCells;i++,cip++,incip++)
6108     {
6109       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6110       int delta(stop-strt);
6111       if(delta>=1)
6112         {
6113           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6114             cp=std::copy(incp+strt,incp+stop,cp);
6115           else
6116             throw INTERP_KERNEL::Exception(msg0);
6117         }
6118       else
6119         throw INTERP_KERNEL::Exception(msg0);
6120       cip[1]=cip[0]+delta;
6121     }
6122   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6123 }
6124
6125 /*!
6126  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6127  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6128  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6129  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6130  * are not used here to avoid the build of big permutation array.
6131  *
6132  * \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
6133  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6134  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6135  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6136  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6137  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6138  * \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
6139  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6140  */
6141 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6142                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6143                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
6144 {
6145   std::vector<const MEDCouplingUMesh *> ms2;
6146   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6147     if(*it)
6148       {
6149         (*it)->checkConnectivityFullyDefined();
6150         ms2.push_back(*it);
6151       }
6152   if(ms2.empty())
6153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6154   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6155   int meshDim=ms2[0]->getMeshDimension();
6156   std::vector<const MEDCouplingUMesh *> m1ssm;
6157   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
6158   //
6159   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6160   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
6161   int fake=0,rk=0;
6162   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6163   ret1->alloc(0,1); ret2->alloc(0,1);
6164   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6165     {
6166       if(meshDim!=(*it)->getMeshDimension())
6167         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6168       if(refCoo!=(*it)->getCoords())
6169         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6170       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6171       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6172       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
6173       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6174         {
6175           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6176           m1ssmSingleAuto.push_back(singleCell);
6177           m1ssmSingle.push_back(singleCell);
6178           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6179         }
6180     }
6181   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6182   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6183   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6184   for(std::size_t i=0;i<m1ssm.size();i++)
6185     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6186   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6187   szOfCellGrpOfSameType=ret1->renumber(renum->begin());
6188   idInMsOfCellGrpOfSameType=ret2->renumber(renum->begin());
6189   return ret0.retn();
6190 }
6191
6192 /*!
6193  * This method returns a newly created DataArrayInt instance.
6194  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6195  */
6196 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
6197 {
6198   checkFullyDefined();
6199   const int *conn=_nodal_connec->begin();
6200   const int *connIndex=_nodal_connec_index->begin();
6201   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6202   for(const int *w=begin;w!=end;w++)
6203     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6204       ret->pushBackSilent(*w);
6205   return ret.retn();
6206 }
6207
6208 /*!
6209  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6210  * are in [0:getNumberOfCells())
6211  */
6212 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
6213 {
6214   checkFullyDefined();
6215   const int *conn=_nodal_connec->begin();
6216   const int *connI=_nodal_connec_index->begin();
6217   int nbOfCells=getNumberOfCells();
6218   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
6219   int *tmp=new int[nbOfCells];
6220   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6221     {
6222       int j=0;
6223       for(const int *i=connI;i!=connI+nbOfCells;i++)
6224         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6225           tmp[std::distance(connI,i)]=j++;
6226     }
6227   DataArrayInt *ret=DataArrayInt::New();
6228   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6229   ret->copyStringInfoFrom(*da);
6230   int *retPtr=ret->getPointer();
6231   const int *daPtr=da->begin();
6232   int nbOfElems=da->getNbOfElems();
6233   for(int k=0;k<nbOfElems;k++)
6234     retPtr[k]=tmp[daPtr[k]];
6235   delete [] tmp;
6236   return ret;
6237 }
6238
6239 /*!
6240  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6241  * This method \b works \b for mesh sorted by type.
6242  * cells whose ids is in 'idsPerGeoType' array.
6243  * This method conserves coords and name of mesh.
6244  */
6245 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6246 {
6247   std::vector<int> code=getDistributionOfTypes();
6248   std::size_t nOfTypesInThis=code.size()/3;
6249   int sz=0,szOfType=0;
6250   for(std::size_t i=0;i<nOfTypesInThis;i++)
6251     {
6252       if(code[3*i]!=type)
6253         sz+=code[3*i+1];
6254       else
6255         szOfType=code[3*i+1];
6256     }
6257   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6258     if(*work<0 || *work>=szOfType)
6259       {
6260         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6261         oss << ". It should be in [0," << szOfType << ") !";
6262         throw INTERP_KERNEL::Exception(oss.str());
6263       }
6264   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6265   int *idsPtr=idsTokeep->getPointer();
6266   int offset=0;
6267   for(std::size_t i=0;i<nOfTypesInThis;i++)
6268     {
6269       if(code[3*i]!=type)
6270         for(int j=0;j<code[3*i+1];j++)
6271           *idsPtr++=offset+j;
6272       else
6273         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6274       offset+=code[3*i+1];
6275     }
6276   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6277   ret->copyTinyInfoFrom(this);
6278   return ret.retn();
6279 }
6280
6281 /*!
6282  * This method returns a vector of size 'this->getNumberOfCells()'.
6283  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6284  */
6285 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
6286 {
6287   int ncell=getNumberOfCells();
6288   std::vector<bool> ret(ncell);
6289   const int *cI=getNodalConnectivityIndex()->begin();
6290   const int *c=getNodalConnectivity()->begin();
6291   for(int i=0;i<ncell;i++)
6292     {
6293       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6294       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6295       ret[i]=cm.isQuadratic();
6296     }
6297   return ret;
6298 }
6299
6300 /*!
6301  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6302  */
6303 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6304 {
6305   if(other->getType()!=UNSTRUCTURED)
6306     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6307   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6308   return MergeUMeshes(this,otherC);
6309 }
6310
6311 /*!
6312  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6313  * computed by averaging coordinates of cell nodes, so this method is not a right
6314  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6315  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6316  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6317  *          components. The caller is to delete this array using decrRef() as it is
6318  *          no more needed.
6319  *  \throw If the coordinates array is not set.
6320  *  \throw If the nodal connectivity of cells is not defined.
6321  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6322  */
6323 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
6324 {
6325   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6326   int spaceDim=getSpaceDimension();
6327   int nbOfCells=getNumberOfCells();
6328   ret->alloc(nbOfCells,spaceDim);
6329   ret->copyStringInfoFrom(*getCoords());
6330   double *ptToFill=ret->getPointer();
6331   const int *nodal=_nodal_connec->begin();
6332   const int *nodalI=_nodal_connec_index->begin();
6333   const double *coor=_coords->begin();
6334   for(int i=0;i<nbOfCells;i++)
6335     {
6336       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6337       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6338       ptToFill+=spaceDim;
6339     }
6340   return ret.retn();
6341 }
6342
6343 /*!
6344  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6345  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
6346  * 
6347  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6348  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6349  * 
6350  * \sa MEDCouplingUMesh::computeCellCenterOfMass
6351  * \throw If \a this is not fully defined (coordinates and connectivity)
6352  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6353  */
6354 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
6355 {
6356   checkFullyDefined();
6357   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6358   int spaceDim=getSpaceDimension();
6359   int nbOfCells=getNumberOfCells();
6360   int nbOfNodes=getNumberOfNodes();
6361   ret->alloc(nbOfCells,spaceDim);
6362   double *ptToFill=ret->getPointer();
6363   const int *nodal=_nodal_connec->begin();
6364   const int *nodalI=_nodal_connec_index->begin();
6365   const double *coor=_coords->begin();
6366   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6367     {
6368       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6369       std::fill(ptToFill,ptToFill+spaceDim,0.);
6370       if(type!=INTERP_KERNEL::NORM_POLYHED)
6371         {
6372           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6373             {
6374               if(*conn>=0 && *conn<nbOfNodes)
6375                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6376               else
6377                 {
6378                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
6379                   throw INTERP_KERNEL::Exception(oss.str());
6380                 }
6381             }
6382           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
6383           if(nbOfNodesInCell>0)
6384             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6385           else
6386             {
6387               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
6388               throw INTERP_KERNEL::Exception(oss.str());
6389             }
6390         }
6391       else
6392         {
6393           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
6394           s.erase(-1);
6395           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
6396             {
6397               if(*it>=0 && *it<nbOfNodes)
6398                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
6399               else
6400                 {
6401                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
6402                   throw INTERP_KERNEL::Exception(oss.str());
6403                 }
6404             }
6405           if(!s.empty())
6406             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
6407           else
6408             {
6409               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
6410               throw INTERP_KERNEL::Exception(oss.str());
6411             }
6412         }
6413     }
6414   return ret.retn();
6415 }
6416
6417 /*!
6418  * Returns a new DataArrayDouble holding barycenters of specified cells. The
6419  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
6420  * are specified via an array of cell ids. 
6421  *  \warning Validity of the specified cell ids is not checked! 
6422  *           Valid range is [ 0, \a this->getNumberOfCells() ).
6423  *  \param [in] begin - an array of cell ids of interest.
6424  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
6425  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
6426  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
6427  *          caller is to delete this array using decrRef() as it is no more needed. 
6428  *  \throw If the coordinates array is not set.
6429  *  \throw If the nodal connectivity of cells is not defined.
6430  *
6431  *  \if ENABLE_EXAMPLES
6432  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
6433  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
6434  *  \endif
6435  */
6436 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6437 {
6438   DataArrayDouble *ret=DataArrayDouble::New();
6439   int spaceDim=getSpaceDimension();
6440   int nbOfTuple=(int)std::distance(begin,end);
6441   ret->alloc(nbOfTuple,spaceDim);
6442   double *ptToFill=ret->getPointer();
6443   double *tmp=new double[spaceDim];
6444   const int *nodal=_nodal_connec->begin();
6445   const int *nodalI=_nodal_connec_index->begin();
6446   const double *coor=_coords->begin();
6447   for(const int *w=begin;w!=end;w++)
6448     {
6449       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6450       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6451       ptToFill+=spaceDim;
6452     }
6453   delete [] tmp;
6454   return ret;
6455 }
6456
6457 /*!
6458  * 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".
6459  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
6460  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
6461  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
6462  * This method is useful to detect 2D cells in 3D space that are not coplanar.
6463  * 
6464  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
6465  * \throw If spaceDim!=3 or meshDim!=2.
6466  * \throw If connectivity of \a this is invalid.
6467  * \throw If connectivity of a cell in \a this points to an invalid node.
6468  */
6469 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
6470 {
6471   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
6472   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6473   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
6474     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
6475   ret->alloc(nbOfCells,4);
6476   double *retPtr(ret->getPointer());
6477   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
6478   const double *coor(_coords->begin());
6479   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
6480     {
6481       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
6482       if(nodalI[1]-nodalI[0]>=3)
6483         {
6484           for(int j=0;j<3;j++)
6485             {
6486               int nodeId(nodal[nodalI[0]+1+j]);
6487               if(nodeId>=0 && nodeId<nbOfNodes)
6488                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
6489               else
6490                 {
6491                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
6492                   throw INTERP_KERNEL::Exception(oss.str());
6493                 }
6494             }
6495         }
6496       else
6497         {
6498           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
6499           throw INTERP_KERNEL::Exception(oss.str());
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   return ret.retn();
6505 }
6506
6507 /*!
6508  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6509  * 
6510  */
6511 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
6512 {
6513   if(!da)
6514     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6515   da->checkAllocated();
6516   std::string name(da->getName());
6517   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(name,0));
6518   if(name.empty())
6519     ret->setName("Mesh");
6520   ret->setCoords(da);
6521   int nbOfTuples(da->getNumberOfTuples());
6522   MCAuto<DataArrayInt> c(DataArrayInt::New()),cI(DataArrayInt::New());
6523   c->alloc(2*nbOfTuples,1);
6524   cI->alloc(nbOfTuples+1,1);
6525   int *cp(c->getPointer()),*cip(cI->getPointer());
6526   *cip++=0;
6527   for(int i=0;i<nbOfTuples;i++)
6528     {
6529       *cp++=INTERP_KERNEL::NORM_POINT1;
6530       *cp++=i;
6531       *cip++=2*(i+1);
6532     }
6533   ret->setConnectivity(c,cI,true);
6534   return ret.retn();
6535 }
6536
6537 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::Build1DMeshFromCoords(DataArrayDouble *da)
6538 {
6539   if(!da)
6540     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build01MeshFromCoords : instance of DataArrayDouble must be not null !");
6541   da->checkAllocated();
6542   std::string name(da->getName());
6543   MCAuto<MEDCouplingUMesh> ret;
6544   {
6545     MCAuto<MEDCouplingCMesh> tmp(MEDCouplingCMesh::New());
6546     MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6547     arr->alloc(da->getNumberOfTuples());
6548     tmp->setCoordsAt(0,arr);
6549     ret=tmp->buildUnstructured();
6550   }
6551   ret->setCoords(da);
6552   if(name.empty())
6553     ret->setName("Mesh");
6554   else
6555     ret->setName(name);
6556   return ret;
6557 }
6558
6559 /*!
6560  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
6561  * Cells and nodes of
6562  * the first mesh precede cells and nodes of the second mesh within the result mesh.
6563  *  \param [in] mesh1 - the first mesh.
6564  *  \param [in] mesh2 - the second mesh.
6565  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6566  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6567  *          is no more needed.
6568  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6569  *  \throw If the coordinates array is not set in none of the meshes.
6570  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6571  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6572  */
6573 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6574 {
6575   std::vector<const MEDCouplingUMesh *> tmp(2);
6576   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6577   return MergeUMeshes(tmp);
6578 }
6579
6580 /*!
6581  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
6582  * Cells and nodes of
6583  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
6584  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
6585  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6586  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6587  *          is no more needed.
6588  *  \throw If \a a.size() == 0.
6589  *  \throw If \a a[ *i* ] == NULL.
6590  *  \throw If the coordinates array is not set in none of the meshes.
6591  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6592  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6593  */
6594 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const std::vector<const MEDCouplingUMesh *>& a)
6595 {
6596   std::size_t sz=a.size();
6597   if(sz==0)
6598     return MergeUMeshesLL(a);
6599   for(std::size_t ii=0;ii<sz;ii++)
6600     if(!a[ii])
6601       {
6602         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6603         throw INTERP_KERNEL::Exception(oss.str());
6604       }
6605   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
6606   std::vector< const MEDCouplingUMesh * > aa(sz);
6607   int spaceDim=-3;
6608   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6609     {
6610       const MEDCouplingUMesh *cur=a[i];
6611       const DataArrayDouble *coo=cur->getCoords();
6612       if(coo)
6613         spaceDim=coo->getNumberOfComponents();
6614     }
6615   if(spaceDim==-3)
6616     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6617   for(std::size_t i=0;i<sz;i++)
6618     {
6619       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6620       aa[i]=bb[i];
6621     }
6622   return MergeUMeshesLL(aa);
6623 }
6624
6625 /*!
6626  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
6627  * dimension and sharing the node coordinates array.
6628  * All cells of the first mesh precede all cells of the second mesh
6629  * within the result mesh.
6630  *  \param [in] mesh1 - the first mesh.
6631  *  \param [in] mesh2 - the second mesh.
6632  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6633  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6634  *          is no more needed.
6635  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6636  *  \throw If the meshes do not share the node coordinates array.
6637  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6638  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6639  */
6640 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6641 {
6642   std::vector<const MEDCouplingUMesh *> tmp(2);
6643   tmp[0]=mesh1; tmp[1]=mesh2;
6644   return MergeUMeshesOnSameCoords(tmp);
6645 }
6646
6647 /*!
6648  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6649  * dimension and sharing the node coordinates array.
6650  * All cells of the *i*-th mesh precede all cells of the
6651  * (*i*+1)-th mesh within the result mesh.
6652  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6653  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6654  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6655  *          is no more needed.
6656  *  \throw If \a a.size() == 0.
6657  *  \throw If \a a[ *i* ] == NULL.
6658  *  \throw If the meshes do not share the node coordinates array.
6659  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6660  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6661  */
6662 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6663 {
6664   if(meshes.empty())
6665     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6666   for(std::size_t ii=0;ii<meshes.size();ii++)
6667     if(!meshes[ii])
6668       {
6669         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6670         throw INTERP_KERNEL::Exception(oss.str());
6671       }
6672   const DataArrayDouble *coords=meshes.front()->getCoords();
6673   int meshDim=meshes.front()->getMeshDimension();
6674   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6675   int meshLgth=0;
6676   int meshIndexLgth=0;
6677   for(;iter!=meshes.end();iter++)
6678     {
6679       if(coords!=(*iter)->getCoords())
6680         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6681       if(meshDim!=(*iter)->getMeshDimension())
6682         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6683       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
6684       meshIndexLgth+=(*iter)->getNumberOfCells();
6685     }
6686   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
6687   nodal->alloc(meshLgth,1);
6688   int *nodalPtr=nodal->getPointer();
6689   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
6690   nodalIndex->alloc(meshIndexLgth+1,1);
6691   int *nodalIndexPtr=nodalIndex->getPointer();
6692   int offset=0;
6693   for(iter=meshes.begin();iter!=meshes.end();iter++)
6694     {
6695       const int *nod=(*iter)->getNodalConnectivity()->begin();
6696       const int *index=(*iter)->getNodalConnectivityIndex()->begin();
6697       int nbOfCells=(*iter)->getNumberOfCells();
6698       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
6699       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6700       if(iter!=meshes.begin())
6701         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6702       else
6703         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6704       offset+=meshLgth2;
6705     }
6706   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6707   ret->setName("merge");
6708   ret->setMeshDimension(meshDim);
6709   ret->setConnectivity(nodal,nodalIndex,true);
6710   ret->setCoords(coords);
6711   return ret;
6712 }
6713
6714 /*!
6715  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6716  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
6717  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
6718  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
6719  * New" mode are returned for each input mesh.
6720  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6721  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
6722  *          valid values [0,1,2], see zipConnectivityTraducer().
6723  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
6724  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
6725  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
6726  *          no more needed.
6727  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6728  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6729  *          is no more needed.
6730  *  \throw If \a meshes.size() == 0.
6731  *  \throw If \a meshes[ *i* ] == NULL.
6732  *  \throw If the meshes do not share the node coordinates array.
6733  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
6734  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
6735  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
6736  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
6737  */
6738 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6739 {
6740   //All checks are delegated to MergeUMeshesOnSameCoords
6741   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6742   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6743   corr.resize(meshes.size());
6744   std::size_t nbOfMeshes=meshes.size();
6745   int offset=0;
6746   const int *o2nPtr=o2n->begin();
6747   for(std::size_t i=0;i<nbOfMeshes;i++)
6748     {
6749       DataArrayInt *tmp=DataArrayInt::New();
6750       int curNbOfCells=meshes[i]->getNumberOfCells();
6751       tmp->alloc(curNbOfCells,1);
6752       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6753       offset+=curNbOfCells;
6754       tmp->setName(meshes[i]->getName());
6755       corr[i]=tmp;
6756     }
6757   return ret.retn();
6758 }
6759
6760 /*!
6761  * Makes all given meshes share the nodal connectivity array. The common connectivity
6762  * array is created by concatenating the connectivity arrays of all given meshes. All
6763  * the given meshes must be of the same space dimension but dimension of cells **can
6764  * differ**. This method is particulary useful in MEDLoader context to build a \ref
6765  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6766  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
6767  *  \param [in,out] meshes - a vector of meshes to update.
6768  *  \throw If any of \a meshes is NULL.
6769  *  \throw If the coordinates array is not set in any of \a meshes.
6770  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6771  *  \throw If \a meshes are of different space dimension.
6772  */
6773 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
6774 {
6775   std::size_t sz=meshes.size();
6776   if(sz==0 || sz==1)
6777     return;
6778   std::vector< const DataArrayDouble * > coords(meshes.size());
6779   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6780   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6781     {
6782       if((*it))
6783         {
6784           (*it)->checkConnectivityFullyDefined();
6785           const DataArrayDouble *coo=(*it)->getCoords();
6786           if(coo)
6787             *it2=coo;
6788           else
6789             {
6790               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6791               oss << " has no coordinate array defined !";
6792               throw INTERP_KERNEL::Exception(oss.str());
6793             }
6794         }
6795       else
6796         {
6797           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6798           oss << " is null !";
6799           throw INTERP_KERNEL::Exception(oss.str());
6800         }
6801     }
6802   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6803   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6804   int offset=(*it)->getNumberOfNodes();
6805   (*it++)->setCoords(res);
6806   for(;it!=meshes.end();it++)
6807     {
6808       int oldNumberOfNodes=(*it)->getNumberOfNodes();
6809       (*it)->setCoords(res);
6810       (*it)->shiftNodeNumbersInConn(offset);
6811       offset+=oldNumberOfNodes;
6812     }
6813 }
6814
6815 /*!
6816  * Merges nodes coincident with a given precision within all given meshes that share
6817  * the nodal connectivity array. The given meshes **can be of different** mesh
6818  * dimension. This method is particulary useful in MEDLoader context to build a \ref
6819  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6820  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
6821  *  \param [in,out] meshes - a vector of meshes to update.
6822  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
6823  *  \throw If any of \a meshes is NULL.
6824  *  \throw If the \a meshes do not share the same node coordinates array.
6825  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6826  */
6827 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
6828 {
6829   if(meshes.empty())
6830     return ;
6831   std::set<const DataArrayDouble *> s;
6832   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6833     {
6834       if(*it)
6835         s.insert((*it)->getCoords());
6836       else
6837         {
6838           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 !";
6839           throw INTERP_KERNEL::Exception(oss.str());
6840         }
6841     }
6842   if(s.size()!=1)
6843     {
6844       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 !";
6845       throw INTERP_KERNEL::Exception(oss.str());
6846     }
6847   const DataArrayDouble *coo=*(s.begin());
6848   if(!coo)
6849     return;
6850   //
6851   DataArrayInt *comm,*commI;
6852   coo->findCommonTuples(eps,-1,comm,commI);
6853   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
6854   int oldNbOfNodes=coo->getNumberOfTuples();
6855   int newNbOfNodes;
6856   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6857   if(oldNbOfNodes==newNbOfNodes)
6858     return ;
6859   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->begin(),newNbOfNodes);
6860   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6861     {
6862       (*it)->renumberNodesInConn(o2n->begin());
6863       (*it)->setCoords(newCoords);
6864     } 
6865 }
6866
6867
6868 /*!
6869  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
6870  */
6871 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6872 {
6873   std::size_t i, ip1;
6874   double v[3]={0.,0.,0.};
6875   std::size_t sz=std::distance(begin,end);
6876   if(isQuadratic)
6877     sz/=2;
6878   for(i=0;i<sz;i++)
6879     {
6880       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];
6881       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6882       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6883     }
6884   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6885
6886   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
6887   // SEG3 forming a circle):
6888   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
6889     {
6890       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
6891       for(std::size_t j=0;j<sz;j++)
6892         {
6893           if (j%2)  // current point i is quadratic, next point i+1 is standard
6894             {
6895               i = sz+j;
6896               ip1 = (j+1)%sz; // ip1 = "i+1"
6897             }
6898           else      // current point i is standard, next point i+1 is quadratic
6899             {
6900               i = j;
6901               ip1 = j+sz;
6902             }
6903           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
6904           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
6905           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
6906         }
6907       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6908     }
6909   return (ret>0.);
6910 }
6911
6912 /*!
6913  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
6914  */
6915 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6916 {
6917   std::vector<std::pair<int,int> > edges;
6918   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6919   const int *bgFace=begin;
6920   for(std::size_t i=0;i<nbOfFaces;i++)
6921     {
6922       const int *endFace=std::find(bgFace+1,end,-1);
6923       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6924       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6925         {
6926           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6927           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6928             return false;
6929           edges.push_back(p1);
6930         }
6931       bgFace=endFace+1;
6932     }
6933   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6934 }
6935
6936 /*!
6937  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
6938  */
6939 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
6940 {
6941   double vec0[3],vec1[3];
6942   std::size_t sz=std::distance(begin,end);
6943   if(sz%2!=0)
6944     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
6945   int nbOfNodes=(int)sz/2;
6946   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
6947   const double *pt0=coords+3*begin[0];
6948   const double *pt1=coords+3*begin[nbOfNodes];
6949   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
6950   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
6951 }
6952
6953 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
6954 {
6955   std::size_t sz=std::distance(begin,end);
6956   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
6957   std::size_t nbOfNodes(sz/2);
6958   std::copy(begin,end,(int *)tmp);
6959   for(std::size_t j=1;j<nbOfNodes;j++)
6960     {
6961       begin[j]=tmp[nbOfNodes-j];
6962       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
6963     }
6964 }
6965
6966 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
6967 {
6968   std::size_t sz=std::distance(begin,end);
6969   if(sz!=4)
6970     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
6971   double vec0[3],vec1[3];
6972   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
6973   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]; 
6974   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;
6975 }
6976
6977 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
6978 {
6979   std::size_t sz=std::distance(begin,end);
6980   if(sz!=5)
6981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
6982   double vec0[3];
6983   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
6984   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
6985   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
6986 }
6987
6988 /*!
6989  * 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 ) 
6990  * 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
6991  * a 2D space.
6992  *
6993  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
6994  * \param [in] coords the coordinates with nb of components exactly equal to 3
6995  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
6996  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
6997  * \param [out] res the result is put at the end of the vector without any alteration of the data.
6998  */
6999 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
7000 {
7001   int nbFaces=std::count(begin+1,end,-1)+1;
7002   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7003   double *vPtr=v->getPointer();
7004   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7005   double *pPtr=p->getPointer();
7006   const int *stFaceConn=begin+1;
7007   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7008     {
7009       const int *endFaceConn=std::find(stFaceConn,end,-1);
7010       ComputeVecAndPtOfFace(eps,coords->begin(),stFaceConn,endFaceConn,vPtr,pPtr);
7011       stFaceConn=endFaceConn+1;
7012     }
7013   pPtr=p->getPointer(); vPtr=v->getPointer();
7014   DataArrayInt *comm1=0,*commI1=0;
7015   v->findCommonTuples(eps,-1,comm1,commI1);
7016   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7017   const int *comm1Ptr=comm1->begin();
7018   const int *commI1Ptr=commI1->begin();
7019   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7020   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7021   //
7022   MCAuto<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7023   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7024   mm->finishInsertingCells();
7025   //
7026   for(int i=0;i<nbOfGrps1;i++)
7027     {
7028       int vecId=comm1Ptr[commI1Ptr[i]];
7029       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7030       DataArrayInt *comm2=0,*commI2=0;
7031       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7032       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7033       const int *comm2Ptr=comm2->begin();
7034       const int *commI2Ptr=commI2->begin();
7035       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7036       for(int j=0;j<nbOfGrps2;j++)
7037         {
7038           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7039             {
7040               res->insertAtTheEnd(begin,end);
7041               res->pushBackSilent(-1);
7042             }
7043           else
7044             {
7045               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7046               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
7047               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7048               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7049               MCAuto<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7050               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7051               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7052               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7053               const int *idsNodePtr=idsNode->begin();
7054               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];
7055               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7056               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7057               if(std::abs(norm)>eps)
7058                 {
7059                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7060                   mm3->rotate(center,vec,angle);
7061                 }
7062               mm3->changeSpaceDimension(2);
7063               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7064               const int *conn4=mm4->getNodalConnectivity()->begin();
7065               const int *connI4=mm4->getNodalConnectivityIndex()->begin();
7066               int nbOfCells=mm4->getNumberOfCells();
7067               for(int k=0;k<nbOfCells;k++)
7068                 {
7069                   int l=0;
7070                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7071                     res->pushBackSilent(idsNodePtr[*work]);
7072                   res->pushBackSilent(-1);
7073                 }
7074             }
7075         }
7076     }
7077   res->popBackSilent();
7078 }
7079
7080 /*!
7081  * 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
7082  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7083  * 
7084  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7085  * \param [in] coords coordinates expected to have 3 components.
7086  * \param [in] begin start of the nodal connectivity of the face.
7087  * \param [in] end end of the nodal connectivity (excluded) of the face.
7088  * \param [out] v the normalized vector of size 3
7089  * \param [out] p the pos of plane
7090  */
7091 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
7092 {
7093   std::size_t nbPoints=std::distance(begin,end);
7094   if(nbPoints<3)
7095     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7096   double vec[3]={0.,0.,0.};
7097   std::size_t j=0;
7098   bool refFound=false;
7099   for(;j<nbPoints-1 && !refFound;j++)
7100     {
7101       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7102       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7103       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7104       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7105       if(norm>eps)
7106         {
7107           refFound=true;
7108           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7109         }
7110     }
7111   for(std::size_t i=j;i<nbPoints-1;i++)
7112     {
7113       double curVec[3];
7114       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7115       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7116       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7117       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7118       if(norm<eps)
7119         continue;
7120       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7121       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];
7122       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7123       if(norm>eps)
7124         {
7125           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7126           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7127           return ;
7128         }
7129     }
7130   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7131 }
7132
7133 /*!
7134  * This method tries to obtain a well oriented polyhedron.
7135  * If the algorithm fails, an exception will be thrown.
7136  */
7137 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
7138 {
7139   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7140   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7141   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7142   isPerm[0]=true;
7143   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7144   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7145   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7146   //
7147   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7148     {
7149       bgFace=begin;
7150       std::size_t smthChanged=0;
7151       for(std::size_t i=0;i<nbOfFaces;i++)
7152         {
7153           endFace=std::find(bgFace+1,end,-1);
7154           nbOfEdgesInFace=std::distance(bgFace,endFace);
7155           if(!isPerm[i])
7156             {
7157               bool b;
7158               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7159                 {
7160                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7161                   std::pair<int,int> p2(p1.second,p1.first);
7162                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7163                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7164                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7165                 }
7166               if(isPerm[i])
7167                 { 
7168                   if(!b)
7169                     std::reverse(bgFace+1,endFace);
7170                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7171                     {
7172                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7173                       std::pair<int,int> p2(p1.second,p1.first);
7174                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7175                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7176                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7177                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7178                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7179                       if(it!=edgesOK.end())
7180                         {
7181                           edgesOK.erase(it);
7182                           edgesFinished.push_back(p1);
7183                         }
7184                       else
7185                         edgesOK.push_back(p1);
7186                     }
7187                 }
7188             }
7189           bgFace=endFace+1;
7190         }
7191       if(smthChanged==0)
7192         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7193     }
7194   if(!edgesOK.empty())
7195     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7196   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7197     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7198       bgFace=begin;
7199       for(std::size_t i=0;i<nbOfFaces;i++)
7200         {
7201           endFace=std::find(bgFace+1,end,-1);
7202           std::reverse(bgFace+1,endFace);
7203           bgFace=endFace+1;
7204         }
7205     }
7206 }
7207
7208
7209 /*!
7210  * This method makes the assumption spacedimension == meshdimension == 2.
7211  * This method works only for linear cells.
7212  * 
7213  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7214  */
7215 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
7216 {
7217   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7218     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7219   MCAuto<MEDCouplingUMesh> skin(computeSkin());
7220   int oldNbOfNodes(skin->getNumberOfNodes());
7221   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
7222   int nbOfNodesExpected(skin->getNumberOfNodes());
7223   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
7224   int nbCells(skin->getNumberOfCells());
7225   if(nbCells==nbOfNodesExpected)
7226     return buildUnionOf2DMeshLinear(skin,n2o);
7227   else if(2*nbCells==nbOfNodesExpected)
7228     return buildUnionOf2DMeshQuadratic(skin,n2o);
7229   else
7230     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
7231 }
7232
7233 /*!
7234  * This method makes the assumption spacedimension == meshdimension == 3.
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_POLYHED in pos#0)
7238  */
7239 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
7240 {
7241   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7242     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7243   MCAuto<MEDCouplingUMesh> m=computeSkin();
7244   const int *conn=m->getNodalConnectivity()->begin();
7245   const int *connI=m->getNodalConnectivityIndex()->begin();
7246   int nbOfCells=m->getNumberOfCells();
7247   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7248   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7249   if(nbOfCells<1)
7250     return ret.retn();
7251   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7252   for(int i=1;i<nbOfCells;i++)
7253     {
7254       *work++=-1;
7255       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7256     }
7257   return ret.retn();
7258 }
7259
7260 /*!
7261  * \brief Creates a graph of cell neighbors
7262  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
7263  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
7264  *  For example
7265  *  - index:  0 3 5 6 6
7266  *  - value:  1 2 3 2 3 3
7267  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7268  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
7269  */
7270 MEDCouplingSkyLineArray* MEDCouplingUMesh::generateGraph() const
7271 {
7272   checkConnectivityFullyDefined();
7273
7274   int meshDim = this->getMeshDimension();
7275   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
7276   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
7277   this->getReverseNodalConnectivity(revConn,indexr);
7278   const int* indexr_ptr=indexr->begin();
7279   const int* revConn_ptr=revConn->begin();
7280
7281   const MEDCoupling::DataArrayInt* index;
7282   const MEDCoupling::DataArrayInt* conn;
7283   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
7284   index=this->getNodalConnectivityIndex();
7285   int nbCells=this->getNumberOfCells();
7286   const int* index_ptr=index->begin();
7287   const int* conn_ptr=conn->begin();
7288
7289   //creating graph arcs (cell to cell relations)
7290   //arcs are stored in terms of (index,value) notation
7291   // 0 3 5 6 6
7292   // 1 2 3 2 3 3
7293   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7294   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
7295
7296   //warning here one node have less than or equal effective number of cell with it
7297   //but cell could have more than effective nodes
7298   //because other equals nodes in other domain (with other global inode)
7299   std::vector <int> cell2cell_index(nbCells+1,0);
7300   std::vector <int> cell2cell;
7301   cell2cell.reserve(3*nbCells);
7302
7303   for (int icell=0; icell<nbCells;icell++)
7304     {
7305       std::map<int,int > counter;
7306       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
7307         {
7308           int inode=conn_ptr[iconn];
7309           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
7310             {
7311               int icell2=revConn_ptr[iconnr];
7312               std::map<int,int>::iterator iter=counter.find(icell2);
7313               if (iter!=counter.end()) (iter->second)++;
7314               else counter.insert(std::make_pair(icell2,1));
7315             }
7316         }
7317       for (std::map<int,int>::const_iterator iter=counter.begin();
7318            iter!=counter.end(); iter++)
7319         if (iter->second >= meshDim)
7320           {
7321             cell2cell_index[icell+1]++;
7322             cell2cell.push_back(iter->first);
7323           }
7324     }
7325   indexr->decrRef();
7326   revConn->decrRef();
7327   cell2cell_index[0]=0;
7328   for (int icell=0; icell<nbCells;icell++)
7329     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
7330
7331   //filling up index and value to create skylinearray structure
7332   MEDCouplingSkyLineArray * array(MEDCouplingSkyLineArray::New(cell2cell_index,cell2cell));
7333   return array;
7334 }
7335
7336
7337 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
7338 {
7339   int nbOfCells=getNumberOfCells();
7340   if(nbOfCells<=0)
7341     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7342   ofs << "  <" << getVTKDataSetType() << ">\n";
7343   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7344   ofs << "      <PointData>\n" << pointData << std::endl;
7345   ofs << "      </PointData>\n";
7346   ofs << "      <CellData>\n" << cellData << std::endl;
7347   ofs << "      </CellData>\n";
7348   ofs << "      <Points>\n";
7349   if(getSpaceDimension()==3)
7350     _coords->writeVTK(ofs,8,"Points",byteData);
7351   else
7352     {
7353       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7354       coo->writeVTK(ofs,8,"Points",byteData);
7355     }
7356   ofs << "      </Points>\n";
7357   ofs << "      <Cells>\n";
7358   const int *cPtr=_nodal_connec->begin();
7359   const int *cIPtr=_nodal_connec_index->begin();
7360   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7361   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7362   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7363   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7364   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7365   int szFaceOffsets=0,szConn=0;
7366   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7367     {
7368       *w2=cPtr[cIPtr[i]];
7369       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7370         {
7371           *w1=-1;
7372           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7373           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7374         }
7375       else
7376         {
7377           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7378           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7379           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7380           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7381           w4=std::copy(c.begin(),c.end(),w4);
7382         }
7383     }
7384   types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
7385   types->writeVTK(ofs,8,"UInt8","types",byteData);
7386   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
7387   if(szFaceOffsets!=0)
7388     {//presence of Polyhedra
7389       connectivity->reAlloc(szConn);
7390       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
7391       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7392       w1=faces->getPointer();
7393       for(int i=0;i<nbOfCells;i++)
7394         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7395           {
7396             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7397             *w1++=nbFaces;
7398             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7399             for(int j=0;j<nbFaces;j++)
7400               {
7401                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7402                 *w1++=(int)std::distance(w6,w5);
7403                 w1=std::copy(w6,w5,w1);
7404                 w6=w5+1;
7405               }
7406           }
7407       faces->writeVTK(ofs,8,"Int32","faces",byteData);
7408     }
7409   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
7410   ofs << "      </Cells>\n";
7411   ofs << "    </Piece>\n";
7412   ofs << "  </" << getVTKDataSetType() << ">\n";
7413 }
7414
7415 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
7416 {
7417   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
7418   if(_mesh_dim==-2)
7419     { stream << " Not set !"; return ; }
7420   stream << " Mesh dimension : " << _mesh_dim << ".";
7421   if(_mesh_dim==-1)
7422     return ;
7423   if(!_coords)
7424     { stream << " No coordinates set !"; return ; }
7425   if(!_coords->isAllocated())
7426     { stream << " Coordinates set but not allocated !"; return ; }
7427   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
7428   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
7429   if(!_nodal_connec_index)
7430     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
7431   if(!_nodal_connec_index->isAllocated())
7432     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
7433   int lgth=_nodal_connec_index->getNumberOfTuples();
7434   int cpt=_nodal_connec_index->getNumberOfComponents();
7435   if(cpt!=1 || lgth<1)
7436     return ;
7437   stream << std::endl << "Number of cells : " << lgth-1 << ".";
7438 }
7439
7440 std::string MEDCouplingUMesh::getVTKDataSetType() const
7441 {
7442   return std::string("UnstructuredGrid");
7443 }
7444
7445 std::string MEDCouplingUMesh::getVTKFileExtension() const
7446 {
7447   return std::string("vtu");
7448 }
7449
7450
7451
7452 /**
7453  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
7454  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
7455  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
7456  * The caller is to deal with the resulting DataArrayInt.
7457  *  \throw If the coordinate array is not set.
7458  *  \throw If the nodal connectivity of the cells is not defined.
7459  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
7460  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
7461  *
7462  * \sa DataArrayInt::sortEachPairToMakeALinkedList
7463  */
7464 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
7465 {
7466   checkFullyDefined();
7467   if(getMeshDimension()!=1)
7468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
7469
7470   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
7471   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
7472   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
7473   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
7474   const int *d(_d->begin()), *dI(_dI->begin());
7475   const int *rD(_rD->begin()), *rDI(_rDI->begin());
7476   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
7477   const int * dsi(_dsi->begin());
7478   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
7479   m_points=0;
7480   if (dsii->getNumberOfTuples())
7481     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
7482
7483   int nc(getNumberOfCells());
7484   MCAuto<DataArrayInt> result(DataArrayInt::New());
7485   result->alloc(nc,1);
7486
7487   // set of edges not used so far
7488   std::set<int> edgeSet;
7489   for (int i=0; i<nc; edgeSet.insert(i), i++);
7490
7491   int startSeg=0;
7492   int newIdx=0;
7493   // while we have points with only one neighbor segments
7494   do
7495     {
7496       std::list<int> linePiece;
7497       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
7498       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
7499         {
7500           // Fill the list forward (resp. backward) from the start segment:
7501           int activeSeg = startSeg;
7502           int prevPointId = -20;
7503           int ptId;
7504           while (!edgeSet.empty())
7505             {
7506               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
7507                 {
7508                   if (direction==0)
7509                     linePiece.push_back(activeSeg);
7510                   else
7511                     linePiece.push_front(activeSeg);
7512                   edgeSet.erase(activeSeg);
7513                 }
7514
7515               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
7516               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
7517               if (dsi[ptId] == 1) // hitting the end of the line
7518                 break;
7519               prevPointId = ptId;
7520               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
7521               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
7522             }
7523         }
7524       // Done, save final piece into DA:
7525       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
7526       newIdx += linePiece.size();
7527
7528       // identify next valid start segment (one which is not consumed)
7529       if(!edgeSet.empty())
7530         startSeg = *(edgeSet.begin());
7531     }
7532   while (!edgeSet.empty());
7533   return result.retn();
7534 }
7535
7536 /**
7537  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
7538  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
7539  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
7540  * a minimal creation of new nodes is wanted.
7541  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
7542  * nodes if a SEG3 is split without information of middle.
7543  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
7544  * avoid to have a non conform mesh.
7545  *
7546  * \return int - the number of new nodes created (in most of cases 0).
7547  * 
7548  * \throw If \a this is not coherent.
7549  * \throw If \a this has not spaceDim equal to 2.
7550  * \throw If \a this has not meshDim equal to 2.
7551  * \throw If some subcells needed to be split are orphan.
7552  * \sa MEDCouplingUMesh::conformize2D
7553  */
7554 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
7555 {
7556   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
7557     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
7558   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
7559   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
7560     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
7561   if(midOpt==0 && midOptI==0)
7562     {
7563       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
7564       return 0;
7565     }
7566   else if(midOpt!=0 && midOptI!=0)
7567     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
7568   else
7569     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
7570 }
7571
7572 /*!
7573  * 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
7574  * 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
7575  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7576  * 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
7577  * 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.
7578  * 
7579  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7580  */
7581 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
7582 {
7583   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7584   if(sz>=4)
7585     {
7586       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7587       if(cm.getDimension()==2)
7588         {
7589           const int *node=nodalConnBg+1;
7590           int startNode=*node++;
7591           double refX=coords[2*startNode];
7592           for(;node!=nodalConnEnd;node++)
7593             {
7594               if(coords[2*(*node)]<refX)
7595                 {
7596                   startNode=*node;
7597                   refX=coords[2*startNode];
7598                 }
7599             }
7600           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7601           refX=1e300;
7602           double tmp1;
7603           double tmp2[2];
7604           double angle0=-M_PI/2;
7605           //
7606           int nextNode=-1;
7607           int prevNode=-1;
7608           double resRef;
7609           double angleNext=0.;
7610           while(nextNode!=startNode)
7611             {
7612               nextNode=-1;
7613               resRef=1e300;
7614               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7615                 {
7616                   if(*node!=tmpOut.back() && *node!=prevNode)
7617                     {
7618                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7619                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7620                       double res;
7621                       if(angleM<=angle0)
7622                         res=angle0-angleM;
7623                       else
7624                         res=angle0-angleM+2.*M_PI;
7625                       if(res<resRef)
7626                         {
7627                           nextNode=*node;
7628                           resRef=res;
7629                           angleNext=angleM;
7630                         }
7631                     }
7632                 }
7633               if(nextNode!=startNode)
7634                 {
7635                   angle0=angleNext-M_PI;
7636                   if(angle0<-M_PI)
7637                     angle0+=2*M_PI;
7638                   prevNode=tmpOut.back();
7639                   tmpOut.push_back(nextNode);
7640                 }
7641             }
7642           std::vector<int> tmp3(2*(sz-1));
7643           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7644           std::copy(nodalConnBg+1,nodalConnEnd,it);
7645           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7646             {
7647               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7648               return false;
7649             }
7650           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7651             {
7652               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7653               return false;
7654             }
7655           else
7656             {
7657               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7658               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7659               return true;
7660             }
7661         }
7662       else
7663         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7664     }
7665   else
7666     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7667 }
7668
7669 /*!
7670  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7671  * 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.
7672  * 
7673  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7674  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7675  * \param [in,out] arr array in which the remove operation will be done.
7676  * \param [in,out] arrIndx array in the remove operation will modify
7677  * \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])
7678  * \return true if \b arr and \b arrIndx have been modified, false if not.
7679  */
7680 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
7681 {
7682   if(!arrIndx || !arr)
7683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7684   if(offsetForRemoval<0)
7685     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7686   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7687   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7688   int *arrIPtr=arrIndx->getPointer();
7689   *arrIPtr++=0;
7690   int previousArrI=0;
7691   const int *arrPtr=arr->begin();
7692   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7693   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7694     {
7695       if(*arrIPtr-previousArrI>offsetForRemoval)
7696         {
7697           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7698             {
7699               if(s.find(*work)==s.end())
7700                 arrOut.push_back(*work);
7701             }
7702         }
7703       previousArrI=*arrIPtr;
7704       *arrIPtr=(int)arrOut.size();
7705     }
7706   if(arr->getNumberOfTuples()==(int)arrOut.size())
7707     return false;
7708   arr->alloc((int)arrOut.size(),1);
7709   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7710   return true;
7711 }
7712
7713 /*!
7714  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7715  * (\ref numbering-indirect).
7716  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7717  * The selection of extraction is done standardly in new2old format.
7718  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7719  *
7720  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7721  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7722  * \param [in] arrIn arr origin array from which the extraction will be done.
7723  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7724  * \param [out] arrOut the resulting array
7725  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7726  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
7727  */
7728 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7729                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7730 {
7731   if(!arrIn || !arrIndxIn)
7732     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7733   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7734   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7735     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
7736   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7737   const int *arrInPtr=arrIn->begin();
7738   const int *arrIndxPtr=arrIndxIn->begin();
7739   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7740   if(nbOfGrps<0)
7741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7742   int maxSizeOfArr=arrIn->getNumberOfTuples();
7743   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7744   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7745   arrIo->alloc((int)(sz+1),1);
7746   const int *idsIt=idsOfSelectBg;
7747   int *work=arrIo->getPointer();
7748   *work++=0;
7749   int lgth=0;
7750   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7751     {
7752       if(*idsIt>=0 && *idsIt<nbOfGrps)
7753         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7754       else
7755         {
7756           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7757           throw INTERP_KERNEL::Exception(oss.str());
7758         }
7759       if(lgth>=work[-1])
7760         *work=lgth;
7761       else
7762         {
7763           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7764           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7765           throw INTERP_KERNEL::Exception(oss.str());
7766         }
7767     }
7768   arro->alloc(lgth,1);
7769   work=arro->getPointer();
7770   idsIt=idsOfSelectBg;
7771   for(std::size_t i=0;i<sz;i++,idsIt++)
7772     {
7773       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7774         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7775       else
7776         {
7777           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7778           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7779           throw INTERP_KERNEL::Exception(oss.str());
7780         }
7781     }
7782   arrOut=arro.retn();
7783   arrIndexOut=arrIo.retn();
7784 }
7785
7786 /*!
7787  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7788  * (\ref numbering-indirect).
7789  * 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 ).
7790  * The selection of extraction is done standardly in new2old format.
7791  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7792  *
7793  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
7794  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
7795  * \param [in] idsOfSelectStep
7796  * \param [in] arrIn arr origin array from which the extraction will be done.
7797  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7798  * \param [out] arrOut the resulting array
7799  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7800  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
7801  */
7802 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7803                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7804 {
7805   if(!arrIn || !arrIndxIn)
7806     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
7807   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7808   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7809     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
7810   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
7811   const int *arrInPtr=arrIn->begin();
7812   const int *arrIndxPtr=arrIndxIn->begin();
7813   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7814   if(nbOfGrps<0)
7815     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7816   int maxSizeOfArr=arrIn->getNumberOfTuples();
7817   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7818   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7819   arrIo->alloc((int)(sz+1),1);
7820   int idsIt=idsOfSelectStart;
7821   int *work=arrIo->getPointer();
7822   *work++=0;
7823   int lgth=0;
7824   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
7825     {
7826       if(idsIt>=0 && idsIt<nbOfGrps)
7827         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
7828       else
7829         {
7830           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7831           throw INTERP_KERNEL::Exception(oss.str());
7832         }
7833       if(lgth>=work[-1])
7834         *work=lgth;
7835       else
7836         {
7837           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
7838           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
7839           throw INTERP_KERNEL::Exception(oss.str());
7840         }
7841     }
7842   arro->alloc(lgth,1);
7843   work=arro->getPointer();
7844   idsIt=idsOfSelectStart;
7845   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
7846     {
7847       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
7848         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
7849       else
7850         {
7851           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
7852           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7853           throw INTERP_KERNEL::Exception(oss.str());
7854         }
7855     }
7856   arrOut=arro.retn();
7857   arrIndexOut=arrIo.retn();
7858 }
7859
7860 /*!
7861  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7862  * 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
7863  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7864  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7865  *
7866  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7867  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7868  * \param [in] arrIn arr origin array from which the extraction will be done.
7869  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7870  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
7871  * \param [in] srcArrIndex index array of \b srcArr
7872  * \param [out] arrOut the resulting array
7873  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7874  * 
7875  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7876  */
7877 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7878                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7879                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7880 {
7881   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7882     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7883   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7884   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7885   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7886   std::vector<bool> v(nbOfTuples,true);
7887   int offset=0;
7888   const int *arrIndxInPtr=arrIndxIn->begin();
7889   const int *srcArrIndexPtr=srcArrIndex->begin();
7890   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7891     {
7892       if(*it>=0 && *it<nbOfTuples)
7893         {
7894           v[*it]=false;
7895           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7896         }
7897       else
7898         {
7899           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7900           throw INTERP_KERNEL::Exception(oss.str());
7901         }
7902     }
7903   srcArrIndexPtr=srcArrIndex->begin();
7904   arrIo->alloc(nbOfTuples+1,1);
7905   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7906   const int *arrInPtr=arrIn->begin();
7907   const int *srcArrPtr=srcArr->begin();
7908   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7909   int *arroPtr=arro->getPointer();
7910   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7911     {
7912       if(v[ii])
7913         {
7914           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7915           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7916         }
7917       else
7918         {
7919           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7920           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7921           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7922         }
7923     }
7924   arrOut=arro.retn();
7925   arrIndexOut=arrIo.retn();
7926 }
7927
7928 /*!
7929  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7930  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7931  *
7932  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7933  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7934  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7935  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7936  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
7937  * \param [in] srcArrIndex index array of \b srcArr
7938  * 
7939  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
7940  */
7941 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7942                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
7943 {
7944   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7945     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7946   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7947   const int *arrIndxInPtr=arrIndxIn->begin();
7948   const int *srcArrIndexPtr=srcArrIndex->begin();
7949   int *arrInOutPtr=arrInOut->getPointer();
7950   const int *srcArrPtr=srcArr->begin();
7951   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7952     {
7953       if(*it>=0 && *it<nbOfTuples)
7954         {
7955           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7956             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7957           else
7958             {
7959               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] !";
7960               throw INTERP_KERNEL::Exception(oss.str());
7961             }
7962         }
7963       else
7964         {
7965           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7966           throw INTERP_KERNEL::Exception(oss.str());
7967         }
7968     }
7969 }
7970
7971 /*!
7972  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7973  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7974  * 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]].
7975  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7976  * A negative value in \b arrIn means that it is ignored.
7977  * 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.
7978  * 
7979  * \param [in] arrIn arr origin array from which the extraction will be done.
7980  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7981  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7982  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
7983  */
7984 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
7985 {
7986   int seed=0,nbOfDepthPeelingPerformed=0;
7987   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
7988 }
7989
7990 /*!
7991  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7992  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7993  * 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]].
7994  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7995  * A negative value in \b arrIn means that it is ignored.
7996  * 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.
7997  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
7998  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
7999  * \param [in] arrIn arr origin array from which the extraction will be done.
8000  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8001  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8002  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8003  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8004  * \sa MEDCouplingUMesh::partitionBySpreadZone
8005  */
8006 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
8007 {
8008   nbOfDepthPeelingPerformed=0;
8009   if(!arrIndxIn)
8010     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8011   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8012   if(nbOfTuples<=0)
8013     {
8014       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8015       return ret;
8016     }
8017   //
8018   std::vector<bool> fetched(nbOfTuples,false);
8019   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8020 }
8021
8022
8023 /*!
8024  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8025  * 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
8026  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8027  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8028  *
8029  * \param [in] start begin of set of ids of the input extraction (included)
8030  * \param [in] end end of set of ids of the input extraction (excluded)
8031  * \param [in] step step of the set of ids in range mode.
8032  * \param [in] arrIn arr origin array from which the extraction will be done.
8033  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8034  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8035  * \param [in] srcArrIndex index array of \b srcArr
8036  * \param [out] arrOut the resulting array
8037  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8038  * 
8039  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8040  */
8041 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8042                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8043                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
8044 {
8045   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8046     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
8047   MCAuto<DataArrayInt> arro=DataArrayInt::New();
8048   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
8049   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8050   int offset=0;
8051   const int *arrIndxInPtr=arrIndxIn->begin();
8052   const int *srcArrIndexPtr=srcArrIndex->begin();
8053   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
8054   int it=start;
8055   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8056     {
8057       if(it>=0 && it<nbOfTuples)
8058         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8059       else
8060         {
8061           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8062           throw INTERP_KERNEL::Exception(oss.str());
8063         }
8064     }
8065   srcArrIndexPtr=srcArrIndex->begin();
8066   arrIo->alloc(nbOfTuples+1,1);
8067   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8068   const int *arrInPtr=arrIn->begin();
8069   const int *srcArrPtr=srcArr->begin();
8070   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8071   int *arroPtr=arro->getPointer();
8072   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8073     {
8074       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8075       if(pos<0)
8076         {
8077           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8078           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8079         }
8080       else
8081         {
8082           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8083           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8084         }
8085     }
8086   arrOut=arro.retn();
8087   arrIndexOut=arrIo.retn();
8088 }
8089
8090 /*!
8091  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8092  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8093  *
8094  * \param [in] start begin of set of ids of the input extraction (included)
8095  * \param [in] end end of set of ids of the input extraction (excluded)
8096  * \param [in] step step of the set of ids in range mode.
8097  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8098  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8099  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8100  * \param [in] srcArrIndex index array of \b srcArr
8101  * 
8102  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8103  */
8104 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8105                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
8106 {
8107   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8108     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
8109   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8110   const int *arrIndxInPtr=arrIndxIn->begin();
8111   const int *srcArrIndexPtr=srcArrIndex->begin();
8112   int *arrInOutPtr=arrInOut->getPointer();
8113   const int *srcArrPtr=srcArr->begin();
8114   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
8115   int it=start;
8116   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8117     {
8118       if(it>=0 && it<nbOfTuples)
8119         {
8120           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
8121             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
8122           else
8123             {
8124               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8125               throw INTERP_KERNEL::Exception(oss.str());
8126             }
8127         }
8128       else
8129         {
8130           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8131           throw INTERP_KERNEL::Exception(oss.str());
8132         }
8133     }
8134 }
8135
8136 /*!
8137  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8138  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8139  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8140  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8141  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8142  * 
8143  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8144  */
8145 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
8146 {
8147   checkFullyDefined();
8148   int mdim=getMeshDimension();
8149   int spaceDim=getSpaceDimension();
8150   if(mdim!=spaceDim)
8151     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8152   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8153   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8154   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
8155   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8156   ret->setCoords(getCoords());
8157   ret->allocateCells((int)partition.size());
8158   //
8159   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8160     {
8161       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8162       MCAuto<DataArrayInt> cell;
8163       switch(mdim)
8164       {
8165         case 2:
8166           cell=tmp->buildUnionOf2DMesh();
8167           break;
8168         case 3:
8169           cell=tmp->buildUnionOf3DMesh();
8170           break;
8171         default:
8172           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8173       }
8174
8175       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->begin()+1);
8176     }
8177   //
8178   ret->finishInsertingCells();
8179   return ret.retn();
8180 }
8181
8182 /*!
8183  * This method partitions \b this into contiguous zone.
8184  * This method only needs a well defined connectivity. Coordinates are not considered here.
8185  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8186  */
8187 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
8188 {
8189   DataArrayInt *neigh=0,*neighI=0;
8190   computeNeighborsOfCells(neigh,neighI);
8191   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8192   return PartitionBySpreadZone(neighAuto,neighIAuto);
8193 }
8194
8195 std::vector<DataArrayInt *> MEDCouplingUMesh::PartitionBySpreadZone(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8196 {
8197   if(!arrIn || !arrIndxIn)
8198     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : null input pointers !");
8199   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8200   int nbOfTuples(arrIndxIn->getNumberOfTuples());
8201   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1 || nbOfTuples<1)
8202     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : invalid arrays in input !");
8203   int nbOfCellsCur(nbOfTuples-1);
8204   std::vector<DataArrayInt *> ret;
8205   if(nbOfCellsCur<=0)
8206     return ret;
8207   std::vector<bool> fetchedCells(nbOfCellsCur,false);
8208   std::vector< MCAuto<DataArrayInt> > ret2;
8209   int seed=0;
8210   while(seed<nbOfCellsCur)
8211     {
8212       int nbOfPeelPerformed=0;
8213       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfPeelPerformed));
8214       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8215     }
8216   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8217     ret.push_back((*it).retn());
8218   return ret;
8219 }
8220
8221 /*!
8222  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8223  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8224  *
8225  * \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.
8226  * \return a newly allocated DataArrayInt to be managed by the caller.
8227  * \throw In case of \a code has not the right format (typically of size 3*n)
8228  */
8229 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
8230 {
8231   MCAuto<DataArrayInt> ret=DataArrayInt::New();
8232   std::size_t nb=code.size()/3;
8233   if(code.size()%3!=0)
8234     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8235   ret->alloc((int)nb,2);
8236   int *retPtr=ret->getPointer();
8237   for(std::size_t i=0;i<nb;i++,retPtr+=2)
8238     {
8239       retPtr[0]=code[3*i+2];
8240       retPtr[1]=code[3*i+2]+code[3*i+1];
8241     }
8242   return ret.retn();
8243 }
8244
8245 /*!
8246  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
8247  * All cells in \a this are expected to be linear 3D cells.
8248  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
8249  * It leads to an increase to number of cells.
8250  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
8251  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
8252  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
8253  *
8254  * \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.
8255  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
8256  * \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. 
8257  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
8258  *          an id of old cell producing it. The caller is to delete this array using
8259  *         decrRef() as it is no more needed.
8260  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
8261  *
8262  * \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
8263  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
8264  * 
8265  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
8266  * \throw If \a this is not fully constituted with linear 3D cells.
8267  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
8268  */
8269 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
8270 {
8271   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
8272   checkConnectivityFullyDefined();
8273   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8274     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
8275   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
8276   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
8277   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
8278   int *retPt(ret->getPointer());
8279   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
8280   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
8281   const int *oldc(_nodal_connec->begin());
8282   const int *oldci(_nodal_connec_index->begin());
8283   const double *coords(_coords->begin());
8284   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
8285     {
8286       std::vector<int> a; std::vector<double> b;
8287       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
8288       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
8289       const int *aa(&a[0]);
8290       if(!b.empty())
8291         {
8292           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
8293             if(*it<0)
8294               *it=(-(*(it))-1+nbNodes);
8295           addPts->insertAtTheEnd(b.begin(),b.end());
8296           nbNodes+=(int)b.size()/3;
8297         }
8298       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
8299         newConn->insertAtTheEnd(aa,aa+4);
8300     }
8301   if(!addPts->empty())
8302     {
8303       addPts->rearrange(3);
8304       nbOfAdditionalPoints=addPts->getNumberOfTuples();
8305       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
8306       ret0->setCoords(addPts);
8307     }
8308   else
8309     {
8310       nbOfAdditionalPoints=0;
8311       ret0->setCoords(getCoords());
8312     }
8313   ret0->setNodalConnectivity(newConn);
8314   //
8315   ret->computeOffsetsFull();
8316   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
8317   return ret0.retn();
8318 }
8319
8320 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8321     _own_cell(true),_cell_id(-1),_nb_cell(0)
8322 {
8323   if(mesh)
8324     {
8325       mesh->incrRef();
8326       _nb_cell=mesh->getNumberOfCells();
8327     }
8328 }
8329
8330 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8331 {
8332   if(_mesh)
8333     _mesh->decrRef();
8334   if(_own_cell)
8335     delete _cell;
8336 }
8337
8338 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8339     _own_cell(false),_cell_id(bg-1),
8340     _nb_cell(end)
8341 {
8342   if(mesh)
8343     mesh->incrRef();
8344 }
8345
8346 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8347 {
8348   _cell_id++;
8349   if(_cell_id<_nb_cell)
8350     {
8351       _cell->next();
8352       return _cell;
8353     }
8354   else
8355     return 0;
8356 }
8357
8358 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8359 {
8360   if(_mesh)
8361     _mesh->incrRef();
8362 }
8363
8364 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8365 {
8366   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8367 }
8368
8369 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8370 {
8371   if(_mesh)
8372     _mesh->decrRef();
8373 }
8374
8375 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8376     _itc(itc),
8377     _bg(bg),_end(end)
8378 {
8379   if(_mesh)
8380     _mesh->incrRef();
8381 }
8382
8383 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8384 {
8385   if(_mesh)
8386     _mesh->decrRef();
8387 }
8388
8389 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8390 {
8391   return _type;
8392 }
8393
8394 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8395 {
8396   return _end-_bg;
8397 }
8398
8399 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8400 {
8401   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8402 }
8403
8404 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8405 {
8406   if(mesh)
8407     {
8408       mesh->incrRef();
8409       _nb_cell=mesh->getNumberOfCells();
8410     }
8411 }
8412
8413 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8414 {
8415   if(_mesh)
8416     _mesh->decrRef();
8417   delete _cell;
8418 }
8419
8420 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8421 {
8422   const int *c=_mesh->getNodalConnectivity()->begin();
8423   const int *ci=_mesh->getNodalConnectivityIndex()->begin();
8424   if(_cell_id<_nb_cell)
8425     {
8426       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8427       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
8428       int startId=_cell_id;
8429       _cell_id+=nbOfElems;
8430       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8431     }
8432   else
8433     return 0;
8434 }
8435
8436 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8437 {
8438   if(mesh)
8439     {
8440       _conn=mesh->getNodalConnectivity()->getPointer();
8441       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8442     }
8443 }
8444
8445 void MEDCouplingUMeshCell::next()
8446 {
8447   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8448     {
8449       _conn+=_conn_lgth;
8450       _conn_indx++;
8451     }
8452   _conn_lgth=_conn_indx[1]-_conn_indx[0];
8453 }
8454
8455 std::string MEDCouplingUMeshCell::repr() const
8456 {
8457   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8458     {
8459       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8460       oss << " : ";
8461       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8462       return oss.str();
8463     }
8464   else
8465     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8466 }
8467
8468 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8469 {
8470   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8471     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8472   else
8473     return INTERP_KERNEL::NORM_ERROR;
8474 }
8475
8476 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8477 {
8478   lgth=_conn_lgth;
8479   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8480     return _conn;
8481   else
8482     return 0;
8483 }