Salome HOME
Bug fix in simplifyPolyhedronCells(). Thanks Antoine G. !
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (EDF R&D)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCouplingCMesh.hxx"
23 #include "MEDCoupling1GTUMesh.hxx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
30 #include "BBTree.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
44 #include "OrientationInverter.hxx"
45 #include "MEDCouplingUMesh_internal.hxx"
46
47 #include <sstream>
48 #include <fstream>
49 #include <numeric>
50 #include <cstring>
51 #include <limits>
52 #include <list>
53
54 using namespace MEDCoupling;
55
56 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
57
58 /// @cond INTERNAL
59 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_PENTA18, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
60 const int MEDCouplingUMesh::MEDCOUPLING2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,32,-1,25,42,36,4};
61 /// @endcond
62
63 MEDCouplingUMesh *MEDCouplingUMesh::New()
64 {
65   return new MEDCouplingUMesh;
66 }
67
68 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
69 {
70   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
71   ret->setName(meshName);
72   ret->setMeshDimension(meshDim);
73   return ret;
74 }
75
76 /*!
77  * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
78  * between \a this and the new mesh.
79  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
80  *          delete this mesh using decrRef() as it is no more needed. 
81  */
82 MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const
83 {
84   return clone(true);
85 }
86
87
88 /*!
89  * Returns a new MEDCouplingUMesh which is a copy of \a this one.
90  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
91  * this mesh are shared by the new mesh.
92  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
93  *          delete this mesh using decrRef() as it is no more needed. 
94  */
95 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
96 {
97   return new MEDCouplingUMesh(*this,recDeepCpy);
98 }
99
100 /*!
101  * This method behaves mostly like MEDCouplingUMesh::deepCopy method, except that only nodal connectivity arrays are deeply copied.
102  * The coordinates are shared between \a this and the returned instance.
103  * 
104  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
105  * \sa MEDCouplingUMesh::deepCopy
106  */
107 MEDCouplingUMesh *MEDCouplingUMesh::deepCopyConnectivityOnly() const
108 {
109   checkConnectivityFullyDefined();
110   MCAuto<MEDCouplingUMesh> ret=clone(false);
111   MCAuto<DataArrayInt> c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy());
112   ret->setConnectivity(c,ci);
113   return ret.retn();
114 }
115
116 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
117 {
118   if(!other)
119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
120   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
121   if(!otherC)
122     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
123   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
124   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
125 }
126
127 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
128 {
129   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
130   return ret;
131 }
132
133 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
134 {
135   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
136   ret.push_back(_nodal_connec);
137   ret.push_back(_nodal_connec_index);
138   return ret;
139 }
140
141 void MEDCouplingUMesh::updateTime() const
142 {
143   MEDCouplingPointSet::updateTime();
144   if(_nodal_connec)
145     {
146       updateTimeWith(*_nodal_connec);
147     }
148   if(_nodal_connec_index)
149     {
150       updateTimeWith(*_nodal_connec_index);
151     }
152 }
153
154 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
155 {
156 }
157
158 /*!
159  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
160  * then \a this mesh is most probably is writable, exchangeable and available for most
161  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
162  * this method to check that all is in order with \a this mesh.
163  *  \throw If the mesh dimension is not set.
164  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
165  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
166  *  \throw If the connectivity data array has more than one component.
167  *  \throw If the connectivity data array has a named component.
168  *  \throw If the connectivity index data array has more than one component.
169  *  \throw If the connectivity index data array has a named component.
170  */
171 void MEDCouplingUMesh::checkConsistencyLight() const
172 {
173   if(_mesh_dim<-1)
174     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
175   if(_mesh_dim!=-1)
176     MEDCouplingPointSet::checkConsistencyLight();
177   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
178     {
179       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
180         {
181           std::ostringstream message;
182           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
183           throw INTERP_KERNEL::Exception(message.str().c_str());
184         }
185     }
186   if(_nodal_connec)
187     {
188       if(_nodal_connec->getNumberOfComponents()!=1)
189         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
190       if(_nodal_connec->getInfoOnComponent(0)!="")
191         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
192     }
193   else
194     if(_mesh_dim!=-1)
195       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
196   if(_nodal_connec_index)
197     {
198       if(_nodal_connec_index->getNumberOfComponents()!=1)
199         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
200       if(_nodal_connec_index->getInfoOnComponent(0)!="")
201         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
202     }
203   else
204     if(_mesh_dim!=-1)
205       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
206 }
207
208 /*!
209  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
210  * then \a this mesh is most probably is writable, exchangeable and available for all
211  * algorithms. <br> In addition to the checks performed by checkConsistencyLight(), this
212  * method thoroughly checks the nodal connectivity.
213  *  \param [in] eps - a not used parameter.
214  *  \throw If the mesh dimension is not set.
215  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
216  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
217  *  \throw If the connectivity data array has more than one component.
218  *  \throw If the connectivity data array has a named component.
219  *  \throw If the connectivity index data array has more than one component.
220  *  \throw If the connectivity index data array has a named component.
221  *  \throw If number of nodes defining an element does not correspond to the type of element.
222  *  \throw If the nodal connectivity includes an invalid node id.
223  */
224 void MEDCouplingUMesh::checkConsistency(double eps) const
225 {
226   checkConsistencyLight();
227   if(_mesh_dim==-1)
228     return ;
229   int meshDim=getMeshDimension();
230   int nbOfNodes=getNumberOfNodes();
231   int nbOfCells=getNumberOfCells();
232   const int *ptr=_nodal_connec->getConstPointer();
233   const int *ptrI=_nodal_connec_index->getConstPointer();
234   for(int i=0;i<nbOfCells;i++)
235     {
236       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
237       if((int)cm.getDimension()!=meshDim)
238         {
239           std::ostringstream oss;
240           oss << "MEDCouplingUMesh::checkConsistency : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
241           throw INTERP_KERNEL::Exception(oss.str());
242         }
243       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
244       if(!cm.isDynamic())
245         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
246           {
247             std::ostringstream oss;
248             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
249             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
250             throw INTERP_KERNEL::Exception(oss.str());
251           }
252       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
253         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
254           {
255             std::ostringstream oss;
256             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
257             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
258             throw INTERP_KERNEL::Exception(oss.str());
259           }
260       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
261         {
262           int nodeId=*w;
263           if(nodeId>=0)
264             {
265               if(nodeId>=nbOfNodes)
266                 {
267                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
268                   throw INTERP_KERNEL::Exception(oss.str());
269                 }
270             }
271           else if(nodeId<-1)
272             {
273               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
274               throw INTERP_KERNEL::Exception(oss.str());
275             }
276           else
277             {
278               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
279                 {
280                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
281                   throw INTERP_KERNEL::Exception(oss.str());
282                 }
283             }
284         }
285     }
286 }
287
288 /*!
289  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
290  * elements contained in the mesh. For more info on the mesh dimension see
291  * \ref MEDCouplingUMeshPage.
292  *  \param [in] meshDim - a new mesh dimension.
293  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
294  */
295 void MEDCouplingUMesh::setMeshDimension(int meshDim)
296 {
297   if(meshDim<-1 || meshDim>3)
298     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
299   _mesh_dim=meshDim;
300   declareAsNew();
301 }
302
303 /*!
304  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
305  * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
306  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
307  *
308  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
309  *
310  *  \if ENABLE_EXAMPLES
311  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
312  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
313  *  \endif
314  */
315 void MEDCouplingUMesh::allocateCells(int nbOfCells)
316 {
317   if(nbOfCells<0)
318     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
319   if(_nodal_connec_index)
320     {
321       _nodal_connec_index->decrRef();
322     }
323   if(_nodal_connec)
324     {
325       _nodal_connec->decrRef();
326     }
327   _nodal_connec_index=DataArrayInt::New();
328   _nodal_connec_index->reserve(nbOfCells+1);
329   _nodal_connec_index->pushBackSilent(0);
330   _nodal_connec=DataArrayInt::New();
331   _nodal_connec->reserve(2*nbOfCells);
332   _types.clear();
333   declareAsNew();
334 }
335
336 /*!
337  * Appends a cell to the connectivity array. For deeper understanding what is
338  * happening see \ref MEDCouplingUMeshNodalConnectivity.
339  *  \param [in] type - type of cell to add.
340  *  \param [in] size - number of nodes constituting this cell.
341  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
342  * 
343  *  \if ENABLE_EXAMPLES
344  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
345  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
346  *  \endif
347  */
348 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
349 {
350   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
351   if(_nodal_connec_index==0)
352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
353   if((int)cm.getDimension()==_mesh_dim)
354     {
355       if(!cm.isDynamic())
356         if(size!=(int)cm.getNumberOfNodes())
357           {
358             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
359             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
360             throw INTERP_KERNEL::Exception(oss.str());
361           }
362       int idx=_nodal_connec_index->back();
363       int val=idx+size+1;
364       _nodal_connec_index->pushBackSilent(val);
365       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
366       _types.insert(type);
367     }
368   else
369     {
370       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
371       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
372       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
373       throw INTERP_KERNEL::Exception(oss.str());
374     }
375 }
376
377 /*!
378  * Compacts data arrays to release unused memory. This method is to be called after
379  * finishing cell insertion using \a this->insertNextCell().
380  * 
381  *  \if ENABLE_EXAMPLES
382  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
383  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
384  *  \endif
385  */
386 void MEDCouplingUMesh::finishInsertingCells()
387 {
388   _nodal_connec->pack();
389   _nodal_connec_index->pack();
390   _nodal_connec->declareAsNew();
391   _nodal_connec_index->declareAsNew();
392   updateTime();
393 }
394
395 /*!
396  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
397  * Useful for python users.
398  */
399 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
400 {
401   return new MEDCouplingUMeshCellIterator(this);
402 }
403
404 /*!
405  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
406  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
407  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
408  * Useful for python users.
409  */
410 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
411 {
412   if(!checkConsecutiveCellTypes())
413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
414   return new MEDCouplingUMeshCellByTypeEntry(this);
415 }
416
417 /*!
418  * Returns a set of all cell types available in \a this mesh.
419  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
420  * \warning this method does not throw any exception even if \a this is not defined.
421  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
422  */
423 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
424 {
425   return _types;
426 }
427
428 /*!
429  * This method returns the sorted list of geometric types in \a this.
430  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
431  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
432  *
433  * \throw if connectivity in \a this is not correctly defined.
434  *  
435  * \sa MEDCouplingMesh::getAllGeoTypes
436  */
437 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
438 {
439   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
440   checkConnectivityFullyDefined();
441   int nbOfCells(getNumberOfCells());
442   if(nbOfCells==0)
443     return ret;
444   if(getNodalConnectivityArrayLen()<1)
445     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
446   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
447   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
448   for(int i=1;i<nbOfCells;i++,ci++)
449     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
450       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
451   return ret;
452 }
453
454 /*!
455  * This method is a method that compares \a this and \a other.
456  * This method compares \b all attributes, even names and component names.
457  */
458 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
459 {
460   if(!other)
461     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
462   std::ostringstream oss; oss.precision(15);
463   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
464   if(!otherC)
465     {
466       reason="mesh given in input is not castable in MEDCouplingUMesh !";
467       return false;
468     }
469   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
470     return false;
471   if(_mesh_dim!=otherC->_mesh_dim)
472     {
473       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
474       reason=oss.str();
475       return false;
476     }
477   if(_types!=otherC->_types)
478     {
479       oss << "umesh geometric type mismatch :\nThis geometric types are :";
480       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
481         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
482       oss << "\nOther geometric types are :";
483       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
484         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
485       reason=oss.str();
486       return false;
487     }
488   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
489     if(_nodal_connec==0 || otherC->_nodal_connec==0)
490       {
491         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
492         return false;
493       }
494   if(_nodal_connec!=otherC->_nodal_connec)
495     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
496       {
497         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
498         return false;
499       }
500   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
501     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
502       {
503         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
504         return false;
505       }
506   if(_nodal_connec_index!=otherC->_nodal_connec_index)
507     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
508       {
509         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
510         return false;
511       }
512   return true;
513 }
514
515 /*!
516  * Checks if data arrays of this mesh (node coordinates, nodal
517  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
518  * not considered.
519  *  \param [in] other - the mesh to compare with.
520  *  \param [in] prec - precision value used to compare node coordinates.
521  *  \return bool - \a true if the two meshes are same.
522  */
523 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
524 {
525   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
526   if(!otherC)
527     return false;
528   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
529     return false;
530   if(_mesh_dim!=otherC->_mesh_dim)
531     return false;
532   if(_types!=otherC->_types)
533     return false;
534   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
535     if(_nodal_connec==0 || otherC->_nodal_connec==0)
536       return false;
537   if(_nodal_connec!=otherC->_nodal_connec)
538     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
539       return false;
540   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
541     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
542       return false;
543   if(_nodal_connec_index!=otherC->_nodal_connec_index)
544     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
545       return false;
546   return true;
547 }
548
549 /*!
550  * Checks if \a this and \a other meshes are geometrically equivalent with high
551  * probability, else an exception is thrown. The meshes are considered equivalent if
552  * (1) meshes contain the same number of nodes and the same number of elements of the
553  * same types (2) three cells of the two meshes (first, last and middle) are based
554  * on coincident nodes (with a specified precision).
555  *  \param [in] other - the mesh to compare with.
556  *  \param [in] prec - the precision used to compare nodes of the two meshes.
557  *  \throw If the two meshes do not match.
558  */
559 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
560 {
561   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
562   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
563   if(!otherC)
564     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
565 }
566
567 /*!
568  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
569  * cells each node belongs to.
570  * \warning For speed reasons, this method does not check if node ids in the nodal
571  *          connectivity correspond to the size of node coordinates array.
572  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
573  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
574  *        dividing cell ids in \a revNodal into groups each referring to one
575  *        node. Its every element (except the last one) is an index pointing to the
576  *         first id of a group of cells. For example cells sharing the node #1 are 
577  *        described by following range of indices: 
578  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
579  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
580  *        Number of cells sharing the *i*-th node is
581  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
582  * \throw If the coordinates array is not set.
583  * \throw If the nodal connectivity of cells is not defined.
584  * 
585  * \if ENABLE_EXAMPLES
586  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
587  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
588  * \endif
589  */
590 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
591 {
592   checkFullyDefined();
593   int nbOfNodes(getNumberOfNodes());
594   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
595   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
596   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
597   const int *conn(_nodal_connec->begin()),*connIndex(_nodal_connec_index->begin());
598   int nbOfCells(getNumberOfCells()),nbOfEltsInRevNodal(0);
599   for(int eltId=0;eltId<nbOfCells;eltId++)
600     {
601       const int *strtNdlConnOfCurCell(conn+connIndex[eltId]+1),*endNdlConnOfCurCell(conn+connIndex[eltId+1]);
602       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
603         if(*iter>=0)//for polyhedrons
604           {
605             nbOfEltsInRevNodal++;
606             revNodalIndxPtr[(*iter)+1]++;
607           }
608     }
609   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
610   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
611   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
612   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
613   for(int eltId=0;eltId<nbOfCells;eltId++)
614     {
615       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
616       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
617       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
618         if(*iter>=0)//for polyhedrons
619           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
620     }
621 }
622
623 /*!
624  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
625  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
626  * describing correspondence between cells of \a this and the result meshes are
627  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
628  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
629  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
630  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
631  * \warning For speed reasons, this method does not check if node ids in the nodal
632  *          connectivity correspond to the size of node coordinates array.
633  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
634  *          to write this mesh to the MED file, its cells must be sorted using
635  *          sortCellsInMEDFileFrmt().
636  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
637  *         each cell of \a this mesh.
638  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
639  *        dividing cell ids in \a desc into groups each referring to one
640  *        cell of \a this mesh. Its every element (except the last one) is an index
641  *        pointing to the first id of a group of cells. For example cells of the
642  *        result mesh bounding the cell #1 of \a this mesh are described by following
643  *        range of indices:
644  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
645  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
646  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
647  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
648  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
649  *         by each cell of the result mesh.
650  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
651  *        in the result mesh,
652  *        dividing cell ids in \a revDesc into groups each referring to one
653  *        cell of the result mesh the same way as \a descIndx divides \a desc.
654  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
655  *        delete this mesh using decrRef() as it is no more needed.
656  *  \throw If the coordinates array is not set.
657  *  \throw If the nodal connectivity of cells is node defined.
658  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
659  *         revDescIndx == NULL.
660  * 
661  *  \if ENABLE_EXAMPLES
662  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
663  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
664  *  \endif
665  * \sa buildDescendingConnectivity2()
666  */
667 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
668 {
669   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
670 }
671
672 /*!
673  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
674  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
675  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
676  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
677  * \sa MEDCouplingUMesh::buildDescendingConnectivity
678  */
679 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
680 {
681   checkFullyDefined();
682   if(getMeshDimension()!=3)
683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
684   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
685 }
686
687 /*!
688  * This method computes the micro edges constituting each cell in \a this. Micro edge is an edge for non quadratic cells. Micro edge is an half edge for quadratic cells.
689  * This method works for both meshes with mesh dimenstion equal to 2 or 3. Dynamical cells are not supported (polygons, polyhedrons...)
690  * 
691  * \sa explode3DMeshTo1D, buildDescendingConnectiviy
692  */
693 MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
694 {
695    checkFullyDefined();
696    switch(getMeshDimension())
697      {
698      case 2:
699        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
700      case 3:
701        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
702      default:
703        throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explodeMeshIntoMicroEdges : Only 2D and 3D supported !");
704      }
705 }
706
707 /*!
708  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
709  * this->getMeshDimension(), that bound cells of \a this mesh. In
710  * addition arrays describing correspondence between cells of \a this and the result
711  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
712  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
713  *  mesh. This method differs from buildDescendingConnectivity() in that apart
714  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
715  * result meshes. So a positive id means that order of nodes in corresponding cells
716  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
717  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
718  * i.e. cell ids are one-based.
719  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
720  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
721  * \warning For speed reasons, this method does not check if node ids in the nodal
722  *          connectivity correspond to the size of node coordinates array.
723  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
724  *          to write this mesh to the MED file, its cells must be sorted using
725  *          sortCellsInMEDFileFrmt().
726  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
727  *         each cell of \a this mesh.
728  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
729  *        dividing cell ids in \a desc into groups each referring to one
730  *        cell of \a this mesh. Its every element (except the last one) is an index
731  *        pointing to the first id of a group of cells. For example cells of the
732  *        result mesh bounding the cell #1 of \a this mesh are described by following
733  *        range of indices:
734  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
735  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
736  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
737  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
738  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
739  *         by each cell of the result mesh.
740  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
741  *        in the result mesh,
742  *        dividing cell ids in \a revDesc into groups each referring to one
743  *        cell of the result mesh the same way as \a descIndx divides \a desc.
744  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
745  *        shares the node coordinates array with \a this mesh. The caller is to
746  *        delete this mesh using decrRef() as it is no more needed.
747  *  \throw If the coordinates array is not set.
748  *  \throw If the nodal connectivity of cells is node defined.
749  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
750  *         revDescIndx == NULL.
751  * 
752  *  \if ENABLE_EXAMPLES
753  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
754  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
755  *  \endif
756  * \sa buildDescendingConnectivity()
757  */
758 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
759 {
760   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
761 }
762
763 /*!
764  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
765  * For speed reasons no check of this will be done. This method calls
766  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
767  * This method lists cell by cell in \b this which are its neighbors. To compute the result
768  * only connectivities are considered.
769  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
770  * The format of return is hence \ref numbering-indirect.
771  *
772  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
773  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
774  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
775  * is equal to the last values in \b neighborsIndx.
776  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
777  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
778  */
779 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
780 {
781   MCAuto<DataArrayInt> desc=DataArrayInt::New();
782   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
783   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
784   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
785   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
786   meshDM1=0;
787   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
788 }
789
790 void MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne(const DataArrayInt *nodeNeigh, const DataArrayInt *nodeNeighI, MCAuto<DataArrayInt>& cellNeigh, MCAuto<DataArrayInt>& cellNeighIndex) const
791 {
792   if(!nodeNeigh || !nodeNeighI)
793     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : null pointer !");
794   checkConsistencyLight();
795   nodeNeigh->checkAllocated(); nodeNeighI->checkAllocated();
796   nodeNeigh->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh");
797   nodeNeighI->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh index");
798   nodeNeighI->checkNbOfTuples(1+getNumberOfNodes(),"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : invalid length");
799   int nbCells(getNumberOfCells());
800   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin()),*ne(nodeNeigh->begin()),*nei(nodeNeighI->begin());
801   cellNeigh=DataArrayInt::New(); cellNeigh->alloc(0,1); cellNeighIndex=DataArrayInt::New(); cellNeighIndex->alloc(1,1); cellNeighIndex->setIJ(0,0,0);
802   for(int i=0;i<nbCells;i++)
803     {
804       std::set<int> s;
805       for(const int *it=c+ci[i]+1;it!=c+ci[i+1];it++)
806         if(*it>=0)
807           s.insert(ne+nei[*it],ne+nei[*it+1]);
808       s.erase(i);
809       cellNeigh->insertAtTheEnd(s.begin(),s.end());
810       cellNeighIndex->pushBackSilent(cellNeigh->getNumberOfTuples());
811     }
812 }
813
814 /*!
815  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
816  * of MEDCouplingUMesh::computeNeighborsOfCells.
817  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
818  * typically the case to extract a set a neighbours,
819  * excluding a set of meshdim-1 cells in input descending connectivity.
820  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
821  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
822  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
823  * are considered.
824  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
825  *
826  * \param [in] desc descending connectivity array.
827  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
828  * \param [in] revDesc reverse descending connectivity array.
829  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
830  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
831  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
832  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
833  */
834 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
835                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
836 {
837   if(!desc || !descIndx || !revDesc || !revDescIndx)
838     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
839   const int *descPtr=desc->begin();
840   const int *descIPtr=descIndx->begin();
841   const int *revDescPtr=revDesc->begin();
842   const int *revDescIPtr=revDescIndx->begin();
843   //
844   int nbCells=descIndx->getNumberOfTuples()-1;
845   MCAuto<DataArrayInt> out0=DataArrayInt::New();
846   MCAuto<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
847   int *out1Ptr=out1->getPointer();
848   *out1Ptr++=0;
849   out0->reserve(desc->getNumberOfTuples());
850   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
851     {
852       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
853         {
854           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
855           s.erase(i);
856           out0->insertAtTheEnd(s.begin(),s.end());
857         }
858       *out1Ptr=out0->getNumberOfTuples();
859     }
860   neighbors=out0.retn();
861   neighborsIndx=out1.retn();
862 }
863
864 /*!
865  * Explodes \a this into edges whatever its dimension.
866  */
867 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::explodeIntoEdges(MCAuto<DataArrayInt>& desc, MCAuto<DataArrayInt>& descIndex, MCAuto<DataArrayInt>& revDesc, MCAuto<DataArrayInt>& revDescIndx) const
868 {
869   checkFullyDefined();
870   int mdim(getMeshDimension());
871   desc=DataArrayInt::New(); descIndex=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
872   MCAuto<MEDCouplingUMesh> mesh1D;
873   switch(mdim)
874   {
875     case 3:
876       {
877         mesh1D=explode3DMeshTo1D(desc,descIndex,revDesc,revDescIndx);
878         break;
879       }
880     case 2:
881       {
882         mesh1D=buildDescendingConnectivity(desc,descIndex,revDesc,revDescIndx);
883         break;
884       }
885     default:
886       {
887         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2] !");
888       }
889   }
890   return mesh1D;
891 }
892
893 /*!
894  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
895  * For speed reasons no check of this will be done. This method calls
896  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
897  * This method lists node by node in \b this which are its neighbors. To compute the result
898  * only connectivities are considered.
899  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
900  *
901  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
902  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
903  * parameter allows to select the right part in this array (\ref numbering-indirect).
904  * The number of tuples is equal to the last values in \b neighborsIndx.
905  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
906  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
907  * 
908  * \sa MEDCouplingUMesh::computeEnlargedNeighborsOfNodes
909  */
910 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
911 {
912   checkFullyDefined();
913   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
914   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
915   MCConstAuto<MEDCouplingUMesh> mesh1D;
916   switch(mdim)
917   {
918     case 3:
919       {
920         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
921         break;
922       }
923     case 2:
924       {
925         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
926         break;
927       }
928     case 1:
929       {
930         mesh1D.takeRef(this);
931         break;
932       }
933     default:
934       {
935         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
936       }
937   }
938   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
939   mesh1D->getReverseNodalConnectivity(desc,descIndx);
940   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
941   ret0->alloc(desc->getNumberOfTuples(),1);
942   int *r0Pt(ret0->getPointer());
943   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
944   for(int i=0;i<nbNodes;i++,rni++)
945     {
946       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
947         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
948     }
949   neighbors=ret0.retn();
950   neighborsIdx=descIndx.retn();
951 }
952
953 /*!
954  * Computes enlarged neighbors for each nodes in \a this. The behavior of this method is close to MEDCouplingUMesh::computeNeighborsOfNodes except that the neighborhood of each node is wider here.
955  * A node j is considered to be in the neighborhood of i if and only if there is a cell in \a this containing in its nodal connectivity both i and j.
956  * This method is useful to find ghost cells of a part of a mesh with a code based on fields on nodes.
957  * 
958  * \sa MEDCouplingUMesh::computeNeighborsOfNodes
959  */
960 void MEDCouplingUMesh::computeEnlargedNeighborsOfNodes(MCAuto<DataArrayInt> &neighbors, MCAuto<DataArrayInt>& neighborsIdx) const
961 {
962   checkFullyDefined();
963   int nbOfNodes(getNumberOfNodes());
964   const int *conn(_nodal_connec->begin()),*connIndex(_nodal_connec_index->begin());
965   int nbOfCells(getNumberOfCells());
966   std::vector< std::set<int> > st0(nbOfNodes);
967   for(int eltId=0;eltId<nbOfCells;eltId++)
968     {
969       const int *strtNdlConnOfCurCell(conn+connIndex[eltId]+1),*endNdlConnOfCurCell(conn+connIndex[eltId+1]);
970       std::set<int> s(strtNdlConnOfCurCell,endNdlConnOfCurCell); s.erase(-1); //for polyhedrons
971       for(std::set<int>::const_iterator iter2=s.begin();iter2!=s.end();iter2++)
972         st0[*iter2].insert(s.begin(),s.end());
973     }
974   neighborsIdx=DataArrayInt::New(); neighborsIdx->alloc(nbOfNodes+1,1); neighborsIdx->setIJ(0,0,0);
975   {
976     int *neighIdx(neighborsIdx->getPointer());
977     for(std::vector< std::set<int> >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++)
978       neighIdx[1]=neighIdx[0]+(*it).size()-1;
979   }
980   neighbors=DataArrayInt::New(); neighbors->alloc(neighborsIdx->back(),1);
981   {
982     const int *neighIdx(neighborsIdx->begin());
983     int *neigh(neighbors->getPointer()),nodeId(0);
984     for(std::vector< std::set<int> >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++,nodeId++)
985       {
986         std::set<int> s(*it); s.erase(nodeId);
987         std::copy(s.begin(),s.end(),neigh+*neighIdx);
988       }
989   }
990 }
991
992 /*!
993  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
994  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
995  * array of cell ids. Pay attention that after conversion all algorithms work slower
996  * with \a this mesh than before conversion. <br> If an exception is thrown during the
997  * conversion due presence of invalid ids in the array of cells to convert, as a
998  * result \a this mesh contains some already converted elements. In this case the 2D
999  * mesh remains valid but 3D mesh becomes \b inconsistent!
1000  *  \warning This method can significantly modify the order of geometric types in \a this,
1001  *          hence, to write this mesh to the MED file, its cells must be sorted using
1002  *          sortCellsInMEDFileFrmt().
1003  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1004  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1005  *         cellIdsToConvertBg.
1006  *  \throw If the coordinates array is not set.
1007  *  \throw If the nodal connectivity of cells is node defined.
1008  *  \throw If dimension of \a this mesh is not either 2 or 3.
1009  *
1010  *  \if ENABLE_EXAMPLES
1011  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1012  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1013  *  \endif
1014  */
1015 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1016 {
1017   checkFullyDefined();
1018   int dim=getMeshDimension();
1019   if(dim<2 || dim>3)
1020     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1021   int nbOfCells(getNumberOfCells());
1022   if(dim==2)
1023     {
1024       const int *connIndex=_nodal_connec_index->begin();
1025       int *conn=_nodal_connec->getPointer();
1026       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1027         {
1028           if(*iter>=0 && *iter<nbOfCells)
1029             {
1030               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1031               if(!cm.isQuadratic())
1032                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1033               else
1034                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1035             }
1036           else
1037             {
1038               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1039               oss << " in range [0," << nbOfCells << ") !";
1040               throw INTERP_KERNEL::Exception(oss.str());
1041             }
1042         }
1043     }
1044   else
1045     {
1046       int *connIndex(_nodal_connec_index->getPointer());
1047       const int *connOld(_nodal_connec->getConstPointer());
1048       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1049       std::vector<bool> toBeDone(nbOfCells,false);
1050       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1051         {
1052           if(*iter>=0 && *iter<nbOfCells)
1053             toBeDone[*iter]=true;
1054           else
1055             {
1056               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1057               oss << " in range [0," << nbOfCells << ") !";
1058               throw INTERP_KERNEL::Exception(oss.str());
1059             }
1060         }
1061       for(int cellId=0;cellId<nbOfCells;cellId++)
1062         {
1063           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1064           int lgthOld(posP1-pos-1);
1065           if(toBeDone[cellId])
1066             {
1067               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1068               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1069               int *tmp(new int[nbOfFaces*lgthOld+1]);
1070               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1071               for(unsigned j=0;j<nbOfFaces;j++)
1072                 {
1073                   INTERP_KERNEL::NormalizedCellType type;
1074                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1075                   work+=offset;
1076                   *work++=-1;
1077                 }
1078               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1079               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1080               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1081               delete [] tmp;
1082             }
1083           else
1084             {
1085               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1086               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1087             }
1088         }
1089       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1090     }
1091   computeTypes();
1092 }
1093
1094 /*!
1095  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1096  * polyhedrons (if \a this is a 3D mesh).
1097  *  \warning As this method is purely for user-friendliness and no optimization is
1098  *          done to avoid construction of a useless vector, this method can be costly
1099  *          in memory.
1100  *  \throw If the coordinates array is not set.
1101  *  \throw If the nodal connectivity of cells is node defined.
1102  *  \throw If dimension of \a this mesh is not either 2 or 3.
1103  */
1104 void MEDCouplingUMesh::convertAllToPoly()
1105 {
1106   int nbOfCells=getNumberOfCells();
1107   std::vector<int> cellIds(nbOfCells);
1108   for(int i=0;i<nbOfCells;i++)
1109     cellIds[i]=i;
1110   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1111 }
1112
1113 /*!
1114  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1115  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1116  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1117  * base facet of the volume and the second half of nodes describes an opposite facet
1118  * having the same number of nodes as the base one. This method converts such
1119  * connectivity to a valid polyhedral format where connectivity of each facet is
1120  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1121  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1122  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1123  * a correct orientation of the first facet of a polyhedron, else orientation of a
1124  * corrected cell is reverse.<br>
1125  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1126  * it releases the user from boring description of polyhedra connectivity in the valid
1127  * format.
1128  *  \throw If \a this->getMeshDimension() != 3.
1129  *  \throw If \a this->getSpaceDimension() != 3.
1130  *  \throw If the nodal connectivity of cells is not defined.
1131  *  \throw If the coordinates array is not set.
1132  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1133  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1134  *
1135  *  \if ENABLE_EXAMPLES
1136  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1137  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1138  *  \endif
1139  */
1140 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1141 {
1142   checkFullyDefined();
1143   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1144     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1145   int nbOfCells=getNumberOfCells();
1146   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1147   newCi->alloc(nbOfCells+1,1);
1148   int *newci=newCi->getPointer();
1149   const int *ci=_nodal_connec_index->getConstPointer();
1150   const int *c=_nodal_connec->getConstPointer();
1151   newci[0]=0;
1152   for(int i=0;i<nbOfCells;i++)
1153     {
1154       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1155       if(type==INTERP_KERNEL::NORM_POLYHED)
1156         {
1157           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1158             {
1159               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1160               throw INTERP_KERNEL::Exception(oss.str());
1161             }
1162           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1163           if(n2%2!=0)
1164             {
1165               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
1166               throw INTERP_KERNEL::Exception(oss.str());
1167             }
1168           int n1=(int)(n2/2);
1169           newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
1170         }
1171       else
1172         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1173     }
1174   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1175   newC->alloc(newci[nbOfCells],1);
1176   int *newc=newC->getPointer();
1177   for(int i=0;i<nbOfCells;i++)
1178     {
1179       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1180       if(type==INTERP_KERNEL::NORM_POLYHED)
1181         {
1182           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1183           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1184           *newc++=-1;
1185           for(std::size_t j=0;j<n1;j++)
1186             {
1187               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1188               newc[n1+5*j]=-1;
1189               newc[n1+5*j+1]=c[ci[i]+1+j];
1190               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1191               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1192               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1193             }
1194           newc+=n1*6;
1195         }
1196       else
1197         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1198     }
1199   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1200   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1201 }
1202
1203
1204 /*!
1205  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1206  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1207  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1208  *          to write this mesh to the MED file, its cells must be sorted using
1209  *          sortCellsInMEDFileFrmt().
1210  * \warning Cells (and most notably polyhedrons) must be correctly oriented for this to work
1211  *          properly. See orientCorrectlyPolyhedrons() and arePolyhedronsNotCorrectlyOriented().
1212  * \return \c true if at least one cell has been converted, \c false else. In the
1213  *         last case the nodal connectivity remains unchanged.
1214  * \throw If the coordinates array is not set.
1215  * \throw If the nodal connectivity of cells is not defined.
1216  * \throw If \a this->getMeshDimension() < 0.
1217  */
1218 bool MEDCouplingUMesh::unPolyze()
1219 {
1220   checkFullyDefined();
1221   int mdim=getMeshDimension();
1222   if(mdim<0)
1223     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1224   if(mdim<=1)
1225     return false;
1226   int nbOfCells=getNumberOfCells();
1227   if(nbOfCells<1)
1228     return false;
1229   int initMeshLgth=getNodalConnectivityArrayLen();
1230   int *conn=_nodal_connec->getPointer();
1231   int *index=_nodal_connec_index->getPointer();
1232   int posOfCurCell=0;
1233   int newPos=0;
1234   int lgthOfCurCell;
1235   bool ret=false;
1236   for(int i=0;i<nbOfCells;i++)
1237     {
1238       lgthOfCurCell=index[i+1]-posOfCurCell;
1239       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1240       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1241       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1242       int newLgth;
1243       if(cm.isDynamic())
1244         {
1245           switch(cm.getDimension())
1246           {
1247             case 2:
1248               {
1249                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1250                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1251                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1252                 break;
1253               }
1254             case 3:
1255               {
1256                 int nbOfFaces,lgthOfPolyhConn;
1257                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1258                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1259                 break;
1260               }
1261             case 1:
1262               {
1263                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1264                 break;
1265               }
1266           }
1267           ret=ret || (newType!=type);
1268           conn[newPos]=newType;
1269           newPos+=newLgth+1;
1270           posOfCurCell=index[i+1];
1271           index[i+1]=newPos;
1272         }
1273       else
1274         {
1275           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1276           newPos+=lgthOfCurCell;
1277           posOfCurCell+=lgthOfCurCell;
1278           index[i+1]=newPos;
1279         }
1280     }
1281   if(newPos!=initMeshLgth)
1282     _nodal_connec->reAlloc(newPos);
1283   if(ret)
1284     computeTypes();
1285   return ret;
1286 }
1287
1288 /*!
1289  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1290  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1291  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1292  *
1293  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal 
1294  *             precision.
1295  */
1296 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1297 {
1298   checkFullyDefined();
1299   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1300     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1301   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1302   coords->recenterForMaxPrecision(eps);
1303   //
1304   int nbOfCells=getNumberOfCells();
1305   const int *conn=_nodal_connec->getConstPointer();
1306   const int *index=_nodal_connec_index->getConstPointer();
1307   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1308   connINew->alloc(nbOfCells+1,1);
1309   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1310   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1311   MCAuto<DataArrayInt> E_Fi(DataArrayInt::New()), E_F(DataArrayInt::New()), F_Ei(DataArrayInt::New()), F_E(DataArrayInt::New());
1312   MCAuto<MEDCouplingUMesh> m_faces(buildDescendingConnectivity(E_F, E_Fi, F_E, F_Ei));
1313   bool changed=false;
1314   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1315     {
1316       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1317         {
1318           SimplifyPolyhedronCell(eps,coords, i,connNew, m_faces, E_Fi, E_F, F_Ei, F_E);
1319           changed=true;
1320         }
1321       else
1322         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1323       *connINewPtr=connNew->getNumberOfTuples();
1324     }
1325   if(changed)
1326     setConnectivity(connNew,connINew,false);
1327 }
1328
1329 /*!
1330  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1331  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1332  * the format of the returned DataArrayInt instance.
1333  * 
1334  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1335  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1336  */
1337 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1338 {
1339   checkConnectivityFullyDefined();
1340   const int *maxEltPt(std::max_element(_nodal_connec->begin(),_nodal_connec->end()));
1341   int maxElt(maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1);
1342   std::vector<bool> retS(maxElt,false);
1343   computeNodeIdsAlg(retS);
1344   return DataArrayInt::BuildListOfSwitchedOn(retS);
1345 }
1346
1347 /*!
1348  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1349  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1350  */
1351 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1352 {
1353   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1354   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1355   for(int i=0;i<nbOfCells;i++)
1356     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1357       if(conn[j]>=0)
1358         {
1359           if(conn[j]<nbOfNodes)
1360             nodeIdsInUse[conn[j]]=true;
1361           else
1362             {
1363               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1364               throw INTERP_KERNEL::Exception(oss.str());
1365             }
1366         }
1367 }
1368
1369 /// @cond INTERNAL
1370
1371 struct MEDCouplingAccVisit
1372 {
1373   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1374   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1375   int _new_nb_of_nodes;
1376 };
1377
1378 /// @endcond
1379
1380 /*!
1381  * Finds nodes not used in any cell and returns an array giving a new id to every node
1382  * by excluding the unused nodes, for which the array holds -1. The result array is
1383  * a mapping in "Old to New" mode. 
1384  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1385  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1386  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1387  *          if the node is unused or a new id else. The caller is to delete this
1388  *          array using decrRef() as it is no more needed.  
1389  *  \throw If the coordinates array is not set.
1390  *  \throw If the nodal connectivity of cells is not defined.
1391  *  \throw If the nodal connectivity includes an invalid id.
1392  *
1393  *  \if ENABLE_EXAMPLES
1394  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1395  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1396  *  \endif
1397  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1398  */
1399 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1400 {
1401   nbrOfNodesInUse=-1;
1402   int nbOfNodes(getNumberOfNodes());
1403   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1404   ret->alloc(nbOfNodes,1);
1405   int *traducer=ret->getPointer();
1406   std::fill(traducer,traducer+nbOfNodes,-1);
1407   int nbOfCells=getNumberOfCells();
1408   const int *connIndex=_nodal_connec_index->getConstPointer();
1409   const int *conn=_nodal_connec->getConstPointer();
1410   for(int i=0;i<nbOfCells;i++)
1411     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1412       if(conn[j]>=0)
1413         {
1414           if(conn[j]<nbOfNodes)
1415             traducer[conn[j]]=1;
1416           else
1417             {
1418               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1419               throw INTERP_KERNEL::Exception(oss.str());
1420             }
1421         }
1422   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1423   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1424   return ret.retn();
1425 }
1426
1427 /*!
1428  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1429  * For each cell in \b this the number of nodes constituting cell is computed.
1430  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1431  * So for pohyhedrons some nodes can be counted several times in the returned result.
1432  * 
1433  * \return a newly allocated array
1434  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1435  */
1436 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1437 {
1438   checkConnectivityFullyDefined();
1439   int nbOfCells=getNumberOfCells();
1440   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1441   ret->alloc(nbOfCells,1);
1442   int *retPtr=ret->getPointer();
1443   const int *conn=getNodalConnectivity()->getConstPointer();
1444   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1445   for(int i=0;i<nbOfCells;i++,retPtr++)
1446     {
1447       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1448         *retPtr=connI[i+1]-connI[i]-1;
1449       else
1450         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1451     }
1452   return ret.retn();
1453 }
1454
1455 /*!
1456  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1457  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1458  *
1459  * \return DataArrayInt * - new object to be deallocated by the caller.
1460  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1461  */
1462 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1463 {
1464   checkConnectivityFullyDefined();
1465   int nbOfCells=getNumberOfCells();
1466   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1467   ret->alloc(nbOfCells,1);
1468   int *retPtr=ret->getPointer();
1469   const int *conn=getNodalConnectivity()->getConstPointer();
1470   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1471   for(int i=0;i<nbOfCells;i++,retPtr++)
1472     {
1473       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1474       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1475         *retPtr=(int)s.size();
1476       else
1477         {
1478           s.erase(-1);
1479           *retPtr=(int)s.size();
1480         }
1481     }
1482   return ret.retn();
1483 }
1484
1485 /*!
1486  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1487  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1488  * 
1489  * \return a newly allocated array
1490  */
1491 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1492 {
1493   checkConnectivityFullyDefined();
1494   int nbOfCells=getNumberOfCells();
1495   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1496   ret->alloc(nbOfCells,1);
1497   int *retPtr=ret->getPointer();
1498   const int *conn=getNodalConnectivity()->getConstPointer();
1499   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1500   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1501     {
1502       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1503       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1504     }
1505   return ret.retn();
1506 }
1507
1508 /*!
1509  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1510  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1511  * array mean that the corresponding old node is no more used. 
1512  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1513  *           this->getNumberOfNodes() before call of this method. The caller is to
1514  *           delete this array using decrRef() as it is no more needed. 
1515  *  \throw If the coordinates array is not set.
1516  *  \throw If the nodal connectivity of cells is not defined.
1517  *  \throw If the nodal connectivity includes an invalid id.
1518  *  \sa areAllNodesFetched
1519  *
1520  *  \if ENABLE_EXAMPLES
1521  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1522  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1523  *  \endif
1524  */
1525 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1526 {
1527   return MEDCouplingPointSet::zipCoordsTraducer();
1528 }
1529
1530 /*!
1531  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1532  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1533  */
1534 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1535 {
1536   switch(compType)
1537   {
1538     case 0:
1539       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1540     case 1:
1541       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1542     case 2:
1543       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1544     case 3:
1545       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1546     case 7:
1547       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1548   }
1549   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1550 }
1551
1552 /*!
1553  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1554  */
1555 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1556 {
1557   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1558     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1559   return 0;
1560 }
1561
1562 /*!
1563  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1564  */
1565 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1566 {
1567   int sz=connI[cell1+1]-connI[cell1];
1568   if(sz==connI[cell2+1]-connI[cell2])
1569     {
1570       if(conn[connI[cell1]]==conn[connI[cell2]])
1571         {
1572           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1573           unsigned dim=cm.getDimension();
1574           if(dim!=3)
1575             {
1576               if(dim!=1)
1577                 {
1578                   int sz1=2*(sz-1);
1579                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1580                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1581                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1582                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1583                   return work!=tmp+sz1?1:0;
1584                 }
1585               else
1586                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1587             }
1588           else
1589             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1590         }
1591     }
1592   return 0;
1593 }
1594
1595 /*!
1596  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1597  */
1598 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1599 {
1600   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1601     {
1602       if(conn[connI[cell1]]==conn[connI[cell2]])
1603         {
1604           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1605           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1606           return s1==s2?1:0;
1607         }
1608     }
1609   return 0;
1610 }
1611
1612 /*!
1613  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1614  */
1615 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1616 {
1617   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1618     {
1619       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1620       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1621       return s1==s2?1:0;
1622     }
1623   return 0;
1624 }
1625
1626 /*!
1627  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1628  */
1629 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1630 {
1631   int sz=connI[cell1+1]-connI[cell1];
1632   if(sz==connI[cell2+1]-connI[cell2])
1633     {
1634       if(conn[connI[cell1]]==conn[connI[cell2]])
1635         {
1636           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1637           unsigned dim=cm.getDimension();
1638           if(dim!=3)
1639             {
1640               if(dim!=1)
1641                 {
1642                   int sz1=2*(sz-1);
1643                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1644                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1645                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1646                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1647                   if(work!=tmp+sz1)
1648                     return 1;
1649                   else
1650                     {
1651                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1652                       std::reverse_iterator<int *> it2((int *)tmp);
1653                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1654                         return 2;
1655                       else
1656                         return 0;
1657                     }
1658
1659                   return work!=tmp+sz1?1:0;
1660                 }
1661               else
1662                 {//case of SEG2 and SEG3
1663                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1664                     return 1;
1665                   if(!cm.isQuadratic())
1666                     {
1667                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1668                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1669                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1670                         return 2;
1671                       return 0;
1672                     }
1673                   else
1674                     {
1675                       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])
1676                         return 2;
1677                       return 0;
1678                     }
1679                 }
1680             }
1681           else
1682             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1683         }
1684     }
1685   return 0;
1686 }
1687
1688
1689 /*!
1690  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1691  * by \a compType.
1692  * This method keeps the coordiantes of \a this. This method is time consuming.
1693  *
1694  * \param [in] compType input specifying the technique used to compare cells each other.
1695  *   - 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.
1696  *   - 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)
1697  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1698  *   - 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
1699  * can be used for users not sensitive to orientation of cell
1700  * \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.
1701  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1702  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1703  * \return the correspondance array old to new in a newly allocated array.
1704  * 
1705  */
1706 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1707 {
1708   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1709   getReverseNodalConnectivity(revNodal,revNodalI);
1710   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1711 }
1712
1713 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1714                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1715 {
1716   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1717   int nbOfCells=nodalI->getNumberOfTuples()-1;
1718   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1719   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1720   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1721   std::vector<bool> isFetched(nbOfCells,false);
1722   if(startCellId==0)
1723     {
1724       for(int i=0;i<nbOfCells;i++)
1725         {
1726           if(!isFetched[i])
1727             {
1728               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1729               std::vector<int> v,v2;
1730               if(connOfNode!=connPtr+connIPtr[i+1])
1731                 {
1732                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1733                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1734                   connOfNode++;
1735                 }
1736               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1737                 if(*connOfNode>=0)
1738                   {
1739                     v=v2;
1740                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1741                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1742                     v2.resize(std::distance(v2.begin(),it));
1743                   }
1744               if(v2.size()>1)
1745                 {
1746                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1747                     {
1748                       int pos=commonCellsI->back();
1749                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1750                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1751                         isFetched[*it]=true;
1752                     }
1753                 }
1754             }
1755         }
1756     }
1757   else
1758     {
1759       for(int i=startCellId;i<nbOfCells;i++)
1760         {
1761           if(!isFetched[i])
1762             {
1763               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1764               std::vector<int> v,v2;
1765               if(connOfNode!=connPtr+connIPtr[i+1])
1766                 {
1767                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1768                   connOfNode++;
1769                 }
1770               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1771                 if(*connOfNode>=0)
1772                   {
1773                     v=v2;
1774                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1775                     v2.resize(std::distance(v2.begin(),it));
1776                   }
1777               if(v2.size()>1)
1778                 {
1779                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1780                     {
1781                       int pos=commonCellsI->back();
1782                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1783                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1784                         isFetched[*it]=true;
1785                     }
1786                 }
1787             }
1788         }
1789     }
1790   commonCellsArr=commonCells.retn();
1791   commonCellsIArr=commonCellsI.retn();
1792 }
1793
1794 /*!
1795  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1796  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1797  * than \a this->getNumberOfCells() in the returned array means that there is no
1798  * corresponding cell in \a this mesh.
1799  * It is expected that \a this and \a other meshes share the same node coordinates
1800  * array, if it is not so an exception is thrown. 
1801  *  \param [in] other - the mesh to compare with.
1802  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1803  *         valid values [0,1,2], see zipConnectivityTraducer().
1804  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1805  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1806  *         values. The caller is to delete this array using
1807  *         decrRef() as it is no more needed.
1808  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1809  *         mesh.
1810  *
1811  *  \if ENABLE_EXAMPLES
1812  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1813  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1814  *  \endif
1815  *  \sa checkDeepEquivalOnSameNodesWith()
1816  *  \sa checkGeoEquivalWith()
1817  */
1818 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1819 {
1820   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1821   int nbOfCells=getNumberOfCells();
1822   static const int possibleCompType[]={0,1,2};
1823   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1824     {
1825       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1826       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1827       oss << " !";
1828       throw INTERP_KERNEL::Exception(oss.str());
1829     }
1830   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1831   arr=o2n->subArray(nbOfCells);
1832   arr->setName(other->getName());
1833   int tmp;
1834   if(other->getNumberOfCells()==0)
1835     return true;
1836   return arr->getMaxValue(tmp)<nbOfCells;
1837 }
1838
1839 /*!
1840  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1841  * This method tries to determine if \b other is fully included in \b this.
1842  * The main difference is that this method is not expected to throw exception.
1843  * This method has two outputs :
1844  *
1845  * \param other other mesh
1846  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1847  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1848  */
1849 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1850 {
1851   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1852   DataArrayInt *commonCells=0,*commonCellsI=0;
1853   int thisNbCells=getNumberOfCells();
1854   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1855   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1856   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1857   int otherNbCells=other->getNumberOfCells();
1858   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1859   arr2->alloc(otherNbCells,1);
1860   arr2->fillWithZero();
1861   int *arr2Ptr=arr2->getPointer();
1862   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1863   for(int i=0;i<nbOfCommon;i++)
1864     {
1865       int start=commonCellsPtr[commonCellsIPtr[i]];
1866       if(start<thisNbCells)
1867         {
1868           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1869             {
1870               int sig=commonCellsPtr[j]>0?1:-1;
1871               int val=std::abs(commonCellsPtr[j])-1;
1872               if(val>=thisNbCells)
1873                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1874             }
1875         }
1876     }
1877   arr2->setName(other->getName());
1878   if(arr2->presenceOfValue(0))
1879     return false;
1880   arr=arr2.retn();
1881   return true;
1882 }
1883
1884 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1885 {
1886   if(!other)
1887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1888   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1889   if(!otherC)
1890     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1891   std::vector<const MEDCouplingUMesh *> ms(2);
1892   ms[0]=this;
1893   ms[1]=otherC;
1894   return MergeUMeshesOnSameCoords(ms);
1895 }
1896
1897 /*!
1898  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1899  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1900  * cellIds is not given explicitely but by a range python like.
1901  * 
1902  * \param start
1903  * \param end
1904  * \param step
1905  * \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.
1906  * \return a newly allocated
1907  * 
1908  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1909  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1910  */
1911 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
1912 {
1913   if(getMeshDimension()!=-1)
1914     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
1915   else
1916     {
1917       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
1918       if(newNbOfCells!=1)
1919         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1920       if(start!=0)
1921         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1922       incrRef();
1923       return const_cast<MEDCouplingUMesh *>(this);
1924     }
1925 }
1926
1927 /*!
1928  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1929  * The result mesh shares or not the node coordinates array with \a this mesh depending
1930  * on \a keepCoords parameter.
1931  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1932  *           to write this mesh to the MED file, its cells must be sorted using
1933  *           sortCellsInMEDFileFrmt().
1934  *  \param [in] begin - an array of cell ids to include to the new mesh.
1935  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1936  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1937  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1938  *         by calling zipCoords().
1939  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
1940  *         to delete this mesh using decrRef() as it is no more needed. 
1941  *  \throw If the coordinates array is not set.
1942  *  \throw If the nodal connectivity of cells is not defined.
1943  *  \throw If any cell id in the array \a begin is not valid.
1944  *
1945  *  \if ENABLE_EXAMPLES
1946  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1947  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1948  *  \endif
1949  */
1950 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1951 {
1952   if(getMeshDimension()!=-1)
1953     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
1954   else
1955     {
1956       if(end-begin!=1)
1957         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1958       if(begin[0]!=0)
1959         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1960       incrRef();
1961       return const_cast<MEDCouplingUMesh *>(this);
1962     }
1963 }
1964
1965 /*!
1966  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1967  *
1968  * 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.
1969  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1970  * The number of cells of \b this will remain the same with this method.
1971  *
1972  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
1973  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
1974  * \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 ).
1975  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1976  */
1977 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1978 {
1979   checkConnectivityFullyDefined();
1980   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1981   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1982     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1983   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1984     {
1985       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1986       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1987       throw INTERP_KERNEL::Exception(oss.str());
1988     }
1989   std::size_t nbOfCellsToModify(std::distance(cellIdsBg,cellIdsEnd));
1990   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1991     {
1992       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1993       throw INTERP_KERNEL::Exception(oss.str());
1994     }
1995   std::size_t nbOfCells(getNumberOfCells());
1996   bool easyAssign(true);
1997   const int *connI(_nodal_connec_index->begin());
1998   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->begin();
1999   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2000     {
2001       if(*it>=0 && *it<(int)nbOfCells)
2002         {
2003           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2004         }
2005       else
2006         {
2007           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2008           throw INTERP_KERNEL::Exception(oss.str());
2009         }
2010     }
2011   if(easyAssign)
2012     {
2013       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2014       computeTypes();
2015     }
2016   else
2017     {
2018       DataArrayInt *arrOut=0,*arrIOut=0;
2019       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2020                                                arrOut,arrIOut);
2021       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2022       setConnectivity(arrOut,arrIOut,true);
2023     }
2024 }
2025
2026 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2027 {
2028   checkConnectivityFullyDefined();
2029   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2030   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2031     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2032   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2033     {
2034       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2035       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2036       throw INTERP_KERNEL::Exception(oss.str());
2037     }
2038   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2039   if(nbOfCellsToModify!=(int)otherOnSameCoordsThanThis.getNumberOfCells())
2040     {
2041       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2042       throw INTERP_KERNEL::Exception(oss.str());
2043     }
2044   int nbOfCells=getNumberOfCells();
2045   bool easyAssign=true;
2046   const int *connI=_nodal_connec_index->getConstPointer();
2047   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2048   int it=start;
2049   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2050     {
2051       if(it>=0 && it<nbOfCells)
2052         {
2053           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2054         }
2055       else
2056         {
2057           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2058           throw INTERP_KERNEL::Exception(oss.str());
2059         }
2060     }
2061   if(easyAssign)
2062     {
2063       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2064       computeTypes();
2065     }
2066   else
2067     {
2068       DataArrayInt *arrOut=0,*arrIOut=0;
2069       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2070                                                 arrOut,arrIOut);
2071       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2072       setConnectivity(arrOut,arrIOut,true);
2073     }
2074 }                      
2075
2076
2077 /*!
2078  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2079  * this->getMeshDimension(), that bound some cells of \a this mesh.
2080  * The cells of lower dimension to include to the result mesh are selected basing on
2081  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2082  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2083  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2084  * created mesh shares the node coordinates array with \a this mesh. 
2085  *  \param [in] begin - the array of node ids.
2086  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2087  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2088  *         array \a begin are added, else cells whose any node is in the
2089  *         array \a begin are added.
2090  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2091  *         to delete this mesh using decrRef() as it is no more needed. 
2092  *  \throw If the coordinates array is not set.
2093  *  \throw If the nodal connectivity of cells is not defined.
2094  *  \throw If any node id in \a begin is not valid.
2095  *
2096  *  \if ENABLE_EXAMPLES
2097  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2098  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2099  *  \endif
2100  */
2101 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2102 {
2103   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2104   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2105   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2106   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2107   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2108 }
2109
2110 /*!
2111  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2112  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2113  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2114  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2115  *         by calling zipCoords().
2116  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2117  *         to delete this mesh using decrRef() as it is no more needed. 
2118  *  \throw If the coordinates array is not set.
2119  *  \throw If the nodal connectivity of cells is not defined.
2120  *
2121  *  \if ENABLE_EXAMPLES
2122  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2123  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2124  *  \endif
2125  */
2126 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2127 {
2128   DataArrayInt *desc=DataArrayInt::New();
2129   DataArrayInt *descIndx=DataArrayInt::New();
2130   DataArrayInt *revDesc=DataArrayInt::New();
2131   DataArrayInt *revDescIndx=DataArrayInt::New();
2132   //
2133   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2134   revDesc->decrRef();
2135   desc->decrRef();
2136   descIndx->decrRef();
2137   int nbOfCells=meshDM1->getNumberOfCells();
2138   const int *revDescIndxC=revDescIndx->getConstPointer();
2139   std::vector<int> boundaryCells;
2140   for(int i=0;i<nbOfCells;i++)
2141     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2142       boundaryCells.push_back(i);
2143   revDescIndx->decrRef();
2144   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2145   return ret;
2146 }
2147
2148 /*!
2149  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2150  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2151  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2152  */
2153 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2154 {
2155   checkFullyDefined();
2156   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2157   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2158   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2159   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2160   //
2161   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2162   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2163   //
2164   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2165   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2166   const int *revDescPtr=revDesc->getConstPointer();
2167   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2168   int nbOfCells=getNumberOfCells();
2169   std::vector<bool> ret1(nbOfCells,false);
2170   int sz=0;
2171   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2172     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2173       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2174   //
2175   DataArrayInt *ret2=DataArrayInt::New();
2176   ret2->alloc(sz,1);
2177   int *ret2Ptr=ret2->getPointer();
2178   sz=0;
2179   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2180     if(*it)
2181       *ret2Ptr++=sz;
2182   ret2->setName("BoundaryCells");
2183   return ret2;
2184 }
2185
2186 /*!
2187  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2188  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2189  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2190  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2191  *
2192  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2193  * 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
2194  * equals a cell in \b otherDimM1OnSameCoords.
2195  *
2196  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2197  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2198  *
2199  * \param [in] otherDimM1OnSameCoords
2200  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2201  * \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
2202  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2203  */
2204 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2205 {
2206   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2207     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2208   checkConnectivityFullyDefined();
2209   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2210   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2211     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2212   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2213   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2214   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2215   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2216   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2217   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2218   DataArrayInt *idsOtherInConsti=0;
2219   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2220   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2221   if(!b)
2222     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2223   std::set<int> s1;
2224   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2225     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2226   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2227   s1arr_renum1->sort();
2228   cellIdsRk0=s0arr.retn();
2229   //cellIdsRk1=s_renum1.retn();
2230   cellIdsRk1=s1arr_renum1.retn();
2231 }
2232
2233 /*!
2234  * 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
2235  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2236  * 
2237  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2238  */
2239 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2240 {
2241   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2242   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2243   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2244   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2245   //
2246   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2247   revDesc=0; desc=0; descIndx=0;
2248   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2249   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2250   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2251 }
2252
2253 /*!
2254  * Finds nodes lying on the boundary of \a this mesh.
2255  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2256  *          nodes. The caller is to delete this array using decrRef() as it is no
2257  *          more needed.
2258  *  \throw If the coordinates array is not set.
2259  *  \throw If the nodal connectivity of cells is node defined.
2260  *
2261  *  \if ENABLE_EXAMPLES
2262  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2263  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2264  *  \endif
2265  */
2266 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2267 {
2268   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2269   return skin->computeFetchedNodeIds();
2270 }
2271
2272 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2273 {
2274   incrRef();
2275   return const_cast<MEDCouplingUMesh *>(this);
2276 }
2277
2278 /*!
2279  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2280  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2281  * 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.
2282  * 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.
2283  * 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.
2284  *
2285  * \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
2286  *             parameter is altered during the call.
2287  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2288  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2289  * \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.
2290  *
2291  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2292  */
2293 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2294                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2295 {
2296   typedef MCAuto<DataArrayInt> DAInt;
2297   typedef MCAuto<MEDCouplingUMesh> MCUMesh;
2298
2299   checkFullyDefined();
2300   otherDimM1OnSameCoords.checkFullyDefined();
2301   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2302     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2303   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2304     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2305
2306   // Checking star-shaped M1 group:
2307   DAInt dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2308   MCUMesh meshM2 = otherDimM1OnSameCoords.buildDescendingConnectivity(dt0, dit0, rdt0, rdit0);
2309   DAInt dsi = rdit0->deltaShiftIndex();
2310   DAInt idsTmp0 = dsi->findIdsNotInRange(-1, 3);
2311   if(idsTmp0->getNumberOfTuples())
2312     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group: group is too complex: some points (or edges) have more than two connected segments (or faces)!");
2313   dt0=0; dit0=0; rdt0=0; rdit0=0; idsTmp0=0;
2314
2315   // Get extreme nodes from the group (they won't be duplicated), ie nodes belonging to boundary cells of M1
2316   DAInt xtremIdsM2 = dsi->findIdsEqual(1); dsi = 0;
2317   MCUMesh meshM2Part = static_cast<MEDCouplingUMesh *>(meshM2->buildPartOfMySelf(xtremIdsM2->begin(), xtremIdsM2->end(),true));
2318   DAInt xtrem = meshM2Part->computeFetchedNodeIds();
2319   // Remove from the list points on the boundary of the M0 mesh (those need duplication!)
2320   dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2321   MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;
2322   dsi = rdit0->deltaShiftIndex();
2323   DAInt boundSegs = dsi->findIdsEqual(1);   // boundary segs/faces of the M0 mesh
2324   MCUMesh m0descSkin = static_cast<MEDCouplingUMesh *>(m0desc->buildPartOfMySelf(boundSegs->begin(),boundSegs->end(), true));
2325   DAInt fNodes = m0descSkin->computeFetchedNodeIds();
2326   // In 3D, some points on the boundary of M0 still need duplication:
2327   DAInt notDup = 0;
2328   if (getMeshDimension() == 3)
2329     {
2330       DAInt dnu1=DataArrayInt::New(), dnu2=DataArrayInt::New(), dnu3=DataArrayInt::New(), dnu4=DataArrayInt::New();
2331       MCUMesh m0descSkinDesc = m0descSkin->buildDescendingConnectivity(dnu1, dnu2, dnu3, dnu4);
2332       dnu1=0;dnu2=0;dnu3=0;dnu4=0;
2333       DataArrayInt * corresp=0;
2334       meshM2->areCellsIncludedIn(m0descSkinDesc,2,corresp);
2335       DAInt validIds = corresp->findIdsInRange(0, meshM2->getNumberOfCells());
2336       corresp->decrRef();
2337       if (validIds->getNumberOfTuples())
2338         {
2339           MCUMesh m1IntersecSkin = static_cast<MEDCouplingUMesh *>(m0descSkinDesc->buildPartOfMySelf(validIds->begin(), validIds->end(), true));
2340           DAInt notDuplSkin = m1IntersecSkin->findBoundaryNodes();
2341           DAInt fNodes1 = fNodes->buildSubstraction(notDuplSkin);
2342           notDup = xtrem->buildSubstraction(fNodes1);
2343         }
2344       else
2345         notDup = xtrem->buildSubstraction(fNodes);
2346     }
2347   else
2348     notDup = xtrem->buildSubstraction(fNodes);
2349
2350   // Now compute cells around group (i.e. cells where we will do the propagation to identify the two sub-sets delimited by the group)
2351   DAInt m1Nodes = otherDimM1OnSameCoords.computeFetchedNodeIds();
2352   DAInt dupl = m1Nodes->buildSubstraction(notDup);
2353   DAInt cellsAroundGroup = getCellIdsLyingOnNodes(dupl->begin(), dupl->end(), false);  // false= take cell in, even if not all nodes are in notDup
2354
2355   //
2356   MCUMesh m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true));
2357   int nCells2 = m0Part2->getNumberOfCells();
2358   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2359   MCUMesh m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2360
2361   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2362   DataArrayInt *tmp00=0,*tmp11=0;
2363   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2364   DAInt neighInit00(tmp00);
2365   DAInt neighIInit00(tmp11);
2366   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2367   DataArrayInt *idsTmp=0;
2368   m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2369   DAInt ids(idsTmp);
2370   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2371   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2372   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2373   DataArrayInt *tmp0=0,*tmp1=0;
2374   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2375   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2376   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2377   DAInt neigh00(tmp0);
2378   DAInt neighI00(tmp1);
2379
2380   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2381   int seed = 0, nIter = 0;
2382   int nIterMax = nCells2+1; // Safety net for the loop
2383   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2384   hitCells->fillWithValue(-1);
2385   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2386   cellsToModifyConn0_torenum->alloc(0,1);
2387   while (nIter < nIterMax)
2388     {
2389       DAInt t = hitCells->findIdsEqual(-1);
2390       if (!t->getNumberOfTuples())
2391         break;
2392       // Connex zone without the crack (to compute the next seed really)
2393       int dnu;
2394       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2395       std::size_t cnt(0);
2396       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2397         hitCells->setIJ(*ptr,0,1);
2398       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2399       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2400       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2401       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2402       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2403       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2404       DAInt intersec = nonHitCells->buildIntersection(comple);
2405       if (intersec->getNumberOfTuples())
2406         { seed = intersec->getIJ(0,0); }
2407       else
2408         { break; }
2409       nIter++;
2410     }
2411   if (nIter >= nIterMax)
2412     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2413
2414   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2415   cellsToModifyConn0_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2416   cellsToModifyConn1_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2417   //
2418   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2419   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2420   nodeIdsToDuplicate=dupl.retn();
2421 }
2422
2423 /*!
2424  * This method operates a modification of the connectivity and coords in \b this.
2425  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2426  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2427  * 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
2428  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2429  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2430  * 
2431  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2432  * 
2433  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2434  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2435  */
2436 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2437 {
2438   int nbOfNodes=getNumberOfNodes();
2439   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2440   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2441 }
2442
2443 /*!
2444  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2445  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2446  *
2447  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2448  *
2449  * \sa renumberNodesInConn
2450  */
2451 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2452 {
2453   checkConnectivityFullyDefined();
2454   int *conn(getNodalConnectivity()->getPointer());
2455   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2456   int nbOfCells(getNumberOfCells());
2457   for(int i=0;i<nbOfCells;i++)
2458     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2459       {
2460         int& node=conn[iconn];
2461         if(node>=0)//avoid polyhedron separator
2462           {
2463             node+=offset;
2464           }
2465       }
2466   _nodal_connec->declareAsNew();
2467   updateTime();
2468 }
2469
2470 /*!
2471  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2472  *  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
2473  *  of a big mesh.
2474  */
2475 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2476 {
2477   checkConnectivityFullyDefined();
2478   int *conn(getNodalConnectivity()->getPointer());
2479   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2480   int nbOfCells(getNumberOfCells());
2481   for(int i=0;i<nbOfCells;i++)
2482     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2483       {
2484         int& node=conn[iconn];
2485         if(node>=0)//avoid polyhedron separator
2486           {
2487             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2488             if(it!=newNodeNumbersO2N.end())
2489               {
2490                 node=(*it).second;
2491               }
2492             else
2493               {
2494                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2495                 throw INTERP_KERNEL::Exception(oss.str());
2496               }
2497           }
2498       }
2499   _nodal_connec->declareAsNew();
2500   updateTime();
2501 }
2502
2503 /*!
2504  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2505  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2506  * This method is a generalization of shiftNodeNumbersInConn().
2507  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2508  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2509  *         this->getNumberOfNodes(), in "Old to New" mode. 
2510  *         See \ref numbering for more info on renumbering modes.
2511  *  \throw If the nodal connectivity of cells is not defined.
2512  *
2513  *  \if ENABLE_EXAMPLES
2514  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2515  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2516  *  \endif
2517  */
2518 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2519 {
2520   checkConnectivityFullyDefined();
2521   int *conn=getNodalConnectivity()->getPointer();
2522   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2523   int nbOfCells(getNumberOfCells());
2524   for(int i=0;i<nbOfCells;i++)
2525     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2526       {
2527         int& node=conn[iconn];
2528         if(node>=0)//avoid polyhedron separator
2529           {
2530             node=newNodeNumbersO2N[node];
2531           }
2532       }
2533   _nodal_connec->declareAsNew();
2534   updateTime();
2535 }
2536
2537 /*!
2538  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2539  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2540  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2541  * 
2542  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2543  */
2544 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2545 {
2546   checkConnectivityFullyDefined();
2547   int *conn=getNodalConnectivity()->getPointer();
2548   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2549   int nbOfCells=getNumberOfCells();
2550   for(int i=0;i<nbOfCells;i++)
2551     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2552       {
2553         int& node=conn[iconn];
2554         if(node>=0)//avoid polyhedron separator
2555           {
2556             node+=delta;
2557           }
2558       }
2559   _nodal_connec->declareAsNew();
2560   updateTime();
2561 }
2562
2563 /*!
2564  * This method operates a modification of the connectivity in \b this.
2565  * 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.
2566  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2567  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2568  * 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
2569  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2570  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2571  * 
2572  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2573  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2574  * 
2575  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2576  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2577  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2578  */
2579 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2580 {
2581   checkConnectivityFullyDefined();
2582   std::map<int,int> m;
2583   int val=offset;
2584   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2585     m[*work]=val;
2586   int *conn=getNodalConnectivity()->getPointer();
2587   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2588   int nbOfCells=getNumberOfCells();
2589   for(int i=0;i<nbOfCells;i++)
2590     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2591       {
2592         int& node=conn[iconn];
2593         if(node>=0)//avoid polyhedron separator
2594           {
2595             std::map<int,int>::iterator it=m.find(node);
2596             if(it!=m.end())
2597               node=(*it).second;
2598           }
2599       }
2600   updateTime();
2601 }
2602
2603 /*!
2604  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2605  *
2606  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2607  * After the call of this method the number of cells remains the same as before.
2608  *
2609  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2610  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2611  * be strictly in [0;this->getNumberOfCells()).
2612  *
2613  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2614  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2615  * should be contained in[0;this->getNumberOfCells()).
2616  * 
2617  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2618  * \param check
2619  */
2620 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2621 {
2622   checkConnectivityFullyDefined();
2623   int nbCells=getNumberOfCells();
2624   const int *array=old2NewBg;
2625   if(check)
2626     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2627   //
2628   const int *conn=_nodal_connec->getConstPointer();
2629   const int *connI=_nodal_connec_index->getConstPointer();
2630   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2631   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2632   const int *n2oPtr=n2o->begin();
2633   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2634   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2635   newConn->copyStringInfoFrom(*_nodal_connec);
2636   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2637   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2638   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2639   //
2640   int *newC=newConn->getPointer();
2641   int *newCI=newConnI->getPointer();
2642   int loc=0;
2643   newCI[0]=loc;
2644   for(int i=0;i<nbCells;i++)
2645     {
2646       int pos=n2oPtr[i];
2647       int nbOfElts=connI[pos+1]-connI[pos];
2648       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2649       loc+=nbOfElts;
2650       newCI[i+1]=loc;
2651     }
2652   //
2653   setConnectivity(newConn,newConnI);
2654   if(check)
2655     free(const_cast<int *>(array));
2656 }
2657
2658 /*!
2659  * Finds cells whose bounding boxes intersect a given bounding box.
2660  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2661  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2662  *         zMax (if in 3D). 
2663  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2664  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2665  *         extent of the bounding box of cell to produce an addition to this bounding box.
2666  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2667  *         cells. The caller is to delete this array using decrRef() as it is no more
2668  *         needed. 
2669  *  \throw If the coordinates array is not set.
2670  *  \throw If the nodal connectivity of cells is not defined.
2671  *
2672  *  \if ENABLE_EXAMPLES
2673  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2674  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2675  *  \endif
2676  */
2677 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2678 {
2679   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2680   if(getMeshDimension()==-1)
2681     {
2682       elems->pushBackSilent(0);
2683       return elems.retn();
2684     }
2685   int dim=getSpaceDimension();
2686   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2687   const int* conn      = getNodalConnectivity()->getConstPointer();
2688   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2689   const double* coords = getCoords()->getConstPointer();
2690   int nbOfCells=getNumberOfCells();
2691   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2692     {
2693       for (int i=0; i<dim; i++)
2694         {
2695           elem_bb[i*2]=std::numeric_limits<double>::max();
2696           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2697         }
2698
2699       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2700         {
2701           int node= conn[inode];
2702           if(node>=0)//avoid polyhedron separator
2703             {
2704               for (int idim=0; idim<dim; idim++)
2705                 {
2706                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2707                     {
2708                       elem_bb[idim*2] = coords[node*dim+idim] ;
2709                     }
2710                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2711                     {
2712                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2713                     }
2714                 }
2715             }
2716         }
2717       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2718         elems->pushBackSilent(ielem);
2719     }
2720   return elems.retn();
2721 }
2722
2723 /*!
2724  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2725  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2726  * added in 'elems' parameter.
2727  */
2728 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2729 {
2730   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2731   if(getMeshDimension()==-1)
2732     {
2733       elems->pushBackSilent(0);
2734       return elems.retn();
2735     }
2736   int dim=getSpaceDimension();
2737   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2738   const int* conn      = getNodalConnectivity()->getConstPointer();
2739   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2740   const double* coords = getCoords()->getConstPointer();
2741   int nbOfCells=getNumberOfCells();
2742   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2743     {
2744       for (int i=0; i<dim; i++)
2745         {
2746           elem_bb[i*2]=std::numeric_limits<double>::max();
2747           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2748         }
2749
2750       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2751         {
2752           int node= conn[inode];
2753           if(node>=0)//avoid polyhedron separator
2754             {
2755               for (int idim=0; idim<dim; idim++)
2756                 {
2757                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2758                     {
2759                       elem_bb[idim*2] = coords[node*dim+idim] ;
2760                     }
2761                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2762                     {
2763                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2764                     }
2765                 }
2766             }
2767         }
2768       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2769         elems->pushBackSilent(ielem);
2770     }
2771   return elems.retn();
2772 }
2773
2774 /*!
2775  * Returns a type of a cell by its id.
2776  *  \param [in] cellId - the id of the cell of interest.
2777  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2778  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2779  */
2780 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(std::size_t cellId) const
2781 {
2782   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2783   if(cellId<_nodal_connec_index->getNbOfElems()-1)
2784     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2785   else
2786     {
2787       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2788       throw INTERP_KERNEL::Exception(oss.str());
2789     }
2790 }
2791
2792 /*!
2793  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2794  * This method does not throw exception if geometric type \a type is not in \a this.
2795  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2796  * The coordinates array is not considered here.
2797  *
2798  * \param [in] type the geometric type
2799  * \return cell ids in this having geometric type \a type.
2800  */
2801 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2802 {
2803
2804   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2805   ret->alloc(0,1);
2806   checkConnectivityFullyDefined();
2807   int nbCells=getNumberOfCells();
2808   int mdim=getMeshDimension();
2809   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2810   if(mdim!=(int)cm.getDimension())
2811     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2812   const int *ptI=_nodal_connec_index->getConstPointer();
2813   const int *pt=_nodal_connec->getConstPointer();
2814   for(int i=0;i<nbCells;i++)
2815     {
2816       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2817         ret->pushBackSilent(i);
2818     }
2819   return ret.retn();
2820 }
2821
2822 /*!
2823  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2824  */
2825 std::size_t MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2826 {
2827   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2828   std::size_t nbOfCells(getNumberOfCells()),ret(0);
2829   for(std::size_t i=0;i<nbOfCells;i++)
2830     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2831       ret++;
2832   return ret;
2833 }
2834
2835 /*!
2836  * Returns the nodal connectivity of a given cell.
2837  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2838  * all returned node ids can be used in getCoordinatesOfNode().
2839  *  \param [in] cellId - an id of the cell of interest.
2840  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2841  *         cleared before the appending.
2842  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2843  */
2844 void MEDCouplingUMesh::getNodeIdsOfCell(std::size_t cellId, std::vector<int>& conn) const
2845 {
2846   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2847   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2848     if(*w>=0)
2849       conn.push_back(*w);
2850 }
2851
2852 std::string MEDCouplingUMesh::simpleRepr() const
2853 {
2854   static const char msg0[]="No coordinates specified !";
2855   std::ostringstream ret;
2856   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2857   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2858   int tmpp1,tmpp2;
2859   double tt=getTime(tmpp1,tmpp2);
2860   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2861   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2862   if(_mesh_dim>=-1)
2863     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2864   else
2865     { ret << " Mesh dimension has not been set or is invalid !"; }
2866   if(_coords!=0)
2867     {
2868       const int spaceDim=getSpaceDimension();
2869       ret << spaceDim << "\nInfo attached on space dimension : ";
2870       for(int i=0;i<spaceDim;i++)
2871         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2872       ret << "\n";
2873     }
2874   else
2875     ret << msg0 << "\n";
2876   ret << "Number of nodes : ";
2877   if(_coords!=0)
2878     ret << getNumberOfNodes() << "\n";
2879   else
2880     ret << msg0 << "\n";
2881   ret << "Number of cells : ";
2882   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2883     ret << getNumberOfCells() << "\n";
2884   else
2885     ret << "No connectivity specified !" << "\n";
2886   ret << "Cell types present : ";
2887   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2888     {
2889       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2890       ret << cm.getRepr() << " ";
2891     }
2892   ret << "\n";
2893   return ret.str();
2894 }
2895
2896 std::string MEDCouplingUMesh::advancedRepr() const
2897 {
2898   std::ostringstream ret;
2899   ret << simpleRepr();
2900   ret << "\nCoordinates array : \n___________________\n\n";
2901   if(_coords)
2902     _coords->reprWithoutNameStream(ret);
2903   else
2904     ret << "No array set !\n";
2905   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2906   reprConnectivityOfThisLL(ret);
2907   return ret.str();
2908 }
2909
2910 /*!
2911  * This method returns a C++ code that is a dump of \a this.
2912  * This method will throw if this is not fully defined.
2913  */
2914 std::string MEDCouplingUMesh::cppRepr() const
2915 {
2916   static const char coordsName[]="coords";
2917   static const char connName[]="conn";
2918   static const char connIName[]="connI";
2919   checkFullyDefined();
2920   std::ostringstream ret; ret << "// coordinates" << std::endl;
2921   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2922   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2923   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2924   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2925   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2926   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2927   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2928   return ret.str();
2929 }
2930
2931 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2932 {
2933   std::ostringstream ret;
2934   reprConnectivityOfThisLL(ret);
2935   return ret.str();
2936 }
2937
2938 /*!
2939  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2940  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2941  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2942  * some algos).
2943  * 
2944  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2945  * 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
2946  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2947  */
2948 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2949 {
2950   int mdim=getMeshDimension();
2951   if(mdim<0)
2952     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2953   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2954   MCAuto<DataArrayInt> tmp1,tmp2;
2955   bool needToCpyCT=true;
2956   if(!_nodal_connec)
2957     {
2958       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2959       needToCpyCT=false;
2960     }
2961   else
2962     {
2963       tmp1=_nodal_connec;
2964       tmp1->incrRef();
2965     }
2966   if(!_nodal_connec_index)
2967     {
2968       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2969       needToCpyCT=false;
2970     }
2971   else
2972     {
2973       tmp2=_nodal_connec_index;
2974       tmp2->incrRef();
2975     }
2976   ret->setConnectivity(tmp1,tmp2,false);
2977   if(needToCpyCT)
2978     ret->_types=_types;
2979   if(!_coords)
2980     {
2981       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2982       ret->setCoords(coords);
2983     }
2984   else
2985     ret->setCoords(_coords);
2986   return ret.retn();
2987 }
2988
2989 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2990 {
2991   const int *ptI=_nodal_connec_index->getConstPointer();
2992   const int *pt=_nodal_connec->getConstPointer();
2993   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2994     return ptI[cellId+1]-ptI[cellId]-1;
2995   else
2996     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2997 }
2998
2999 /*!
3000  * Returns types of cells of the specified part of \a this mesh.
3001  * This method avoids computing sub-mesh explicitely to get its types.
3002  *  \param [in] begin - an array of cell ids of interest.
3003  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3004  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3005  *         describing the cell types. 
3006  *  \throw If the coordinates array is not set.
3007  *  \throw If the nodal connectivity of cells is not defined.
3008  *  \sa getAllGeoTypes()
3009  */
3010 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3011 {
3012   checkFullyDefined();
3013   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3014   const int *conn=_nodal_connec->getConstPointer();
3015   const int *connIndex=_nodal_connec_index->getConstPointer();
3016   for(const int *w=begin;w!=end;w++)
3017     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3018   return ret;
3019 }
3020
3021 /*!
3022  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3023  * Optionally updates
3024  * a set of types of cells constituting \a this mesh. 
3025  * This method is for advanced users having prepared their connectivity before. For
3026  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3027  *  \param [in] conn - the nodal connectivity array. 
3028  *  \param [in] connIndex - the nodal connectivity index array.
3029  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3030  *         mesh is updated.
3031  */
3032 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3033 {
3034   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3035   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3036   if(isComputingTypes)
3037     computeTypes();
3038   declareAsNew();
3039 }
3040
3041 /*!
3042  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3043  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3044  */
3045 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCpy):MEDCouplingPointSet(other,deepCpy),_mesh_dim(other._mesh_dim),
3046     _nodal_connec(0),_nodal_connec_index(0),
3047     _types(other._types)
3048 {
3049   if(other._nodal_connec)
3050     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCpy);
3051   if(other._nodal_connec_index)
3052     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCpy);
3053 }
3054
3055 MEDCouplingUMesh::~MEDCouplingUMesh()
3056 {
3057   if(_nodal_connec)
3058     _nodal_connec->decrRef();
3059   if(_nodal_connec_index)
3060     _nodal_connec_index->decrRef();
3061 }
3062
3063 /*!
3064  * Recomputes a set of cell types of \a this mesh. For more info see
3065  * \ref MEDCouplingUMeshNodalConnectivity.
3066  */
3067 void MEDCouplingUMesh::computeTypes()
3068 {
3069   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3070 }
3071
3072
3073 /*!
3074  * Returns a number of cells constituting \a this mesh. 
3075  *  \return int - the number of cells in \a this mesh.
3076  *  \throw If the nodal connectivity of cells is not defined.
3077  */
3078 std::size_t MEDCouplingUMesh::getNumberOfCells() const
3079
3080   if(_nodal_connec_index)
3081     return _nodal_connec_index->getNumberOfTuples()-1;
3082   else
3083     if(_mesh_dim==-1)
3084       return 1;
3085     else
3086       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3087 }
3088
3089 /*!
3090  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3091  * mesh. For more info see \ref meshes.
3092  *  \return int - the dimension of \a this mesh.
3093  *  \throw If the mesh dimension is not defined using setMeshDimension().
3094  */
3095 int MEDCouplingUMesh::getMeshDimension() const
3096 {
3097   if(_mesh_dim<-1)
3098     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3099   return _mesh_dim;
3100 }
3101
3102 /*!
3103  * Returns a length of the nodal connectivity array.
3104  * This method is for test reason. Normally the integer returned is not useable by
3105  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3106  *  \return int - the length of the nodal connectivity array.
3107  */
3108 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3109 {
3110   return _nodal_connec->getNbOfElems();
3111 }
3112
3113 /*!
3114  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3115  */
3116 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3117 {
3118   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3119   tinyInfo.push_back(getMeshDimension());
3120   tinyInfo.push_back(getNumberOfCells());
3121   if(_nodal_connec)
3122     tinyInfo.push_back(getNodalConnectivityArrayLen());
3123   else
3124     tinyInfo.push_back(-1);
3125 }
3126
3127 /*!
3128  * First step of unserialization process.
3129  */
3130 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3131 {
3132   return tinyInfo[6]<=0;
3133 }
3134
3135 /*!
3136  * Second step of serialization process.
3137  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3138  * \param a1
3139  * \param a2
3140  * \param littleStrings
3141  */
3142 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3143 {
3144   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3145   if(tinyInfo[5]!=-1)
3146     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3147 }
3148
3149 /*!
3150  * Third and final step of serialization process.
3151  */
3152 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3153 {
3154   MEDCouplingPointSet::serialize(a1,a2);
3155   if(getMeshDimension()>-1)
3156     {
3157       a1=DataArrayInt::New();
3158       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3159       int *ptA1=a1->getPointer();
3160       const int *conn=getNodalConnectivity()->getConstPointer();
3161       const int *index=getNodalConnectivityIndex()->getConstPointer();
3162       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3163       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3164     }
3165   else
3166     a1=0;
3167 }
3168
3169 /*!
3170  * Second and final unserialization process.
3171  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3172  */
3173 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3174 {
3175   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3176   setMeshDimension(tinyInfo[5]);
3177   if(tinyInfo[7]!=-1)
3178     {
3179       // Connectivity
3180       const int *recvBuffer=a1->getConstPointer();
3181       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3182       myConnecIndex->alloc(tinyInfo[6]+1,1);
3183       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3184       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3185       myConnec->alloc(tinyInfo[7],1);
3186       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3187       setConnectivity(myConnec, myConnecIndex);
3188     }
3189 }
3190
3191
3192
3193 /*!
3194  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3195  * mesh.<br>
3196  * For 1D cells, the returned field contains lengths.<br>
3197  * For 2D cells, the returned field contains areas.<br>
3198  * For 3D cells, the returned field contains volumes.
3199  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3200  *         orientation, i.e. the volume is always positive.
3201  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3202  *         and one time . The caller is to delete this field using decrRef() as it is no
3203  *         more needed.
3204  */
3205 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3206 {
3207   std::string name="MeasureOfMesh_";
3208   name+=getName();
3209   int nbelem=getNumberOfCells();
3210   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3211   field->setName(name);
3212   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3213   array->alloc(nbelem,1);
3214   double *area_vol=array->getPointer();
3215   field->setArray(array) ; array=0;
3216   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3217   field->synchronizeTimeWithMesh();
3218   if(getMeshDimension()!=-1)
3219     {
3220       int ipt;
3221       INTERP_KERNEL::NormalizedCellType type;
3222       int dim_space=getSpaceDimension();
3223       const double *coords=getCoords()->getConstPointer();
3224       const int *connec=getNodalConnectivity()->getConstPointer();
3225       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3226       for(int iel=0;iel<nbelem;iel++)
3227         {
3228           ipt=connec_index[iel];
3229           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3230           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);
3231         }
3232       if(isAbs)
3233         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3234     }
3235   else
3236     {
3237       area_vol[0]=std::numeric_limits<double>::max();
3238     }
3239   return field.retn();
3240 }
3241
3242 /*!
3243  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3244  * mesh.<br>
3245  * For 1D cells, the returned array contains lengths.<br>
3246  * For 2D cells, the returned array contains areas.<br>
3247  * For 3D cells, the returned array contains volumes.
3248  * This method avoids building explicitly a part of \a this mesh to perform the work.
3249  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3250  *         orientation, i.e. the volume is always positive.
3251  *  \param [in] begin - an array of cell ids of interest.
3252  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3253  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3254  *          delete this array using decrRef() as it is no more needed.
3255  * 
3256  *  \if ENABLE_EXAMPLES
3257  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3258  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3259  *  \endif
3260  *  \sa getMeasureField()
3261  */
3262 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3263 {
3264   std::string name="PartMeasureOfMesh_";
3265   name+=getName();
3266   int nbelem=(int)std::distance(begin,end);
3267   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3268   array->setName(name);
3269   array->alloc(nbelem,1);
3270   double *area_vol=array->getPointer();
3271   if(getMeshDimension()!=-1)
3272     {
3273       int ipt;
3274       INTERP_KERNEL::NormalizedCellType type;
3275       int dim_space=getSpaceDimension();
3276       const double *coords=getCoords()->getConstPointer();
3277       const int *connec=getNodalConnectivity()->getConstPointer();
3278       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3279       for(const int *iel=begin;iel!=end;iel++)
3280         {
3281           ipt=connec_index[*iel];
3282           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3283           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3284         }
3285       if(isAbs)
3286         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3287     }
3288   else
3289     {
3290       area_vol[0]=std::numeric_limits<double>::max();
3291     }
3292   return array.retn();
3293 }
3294
3295 /*!
3296  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3297  * \a this one. The returned field contains the dual cell volume for each corresponding
3298  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3299  *  the dual mesh in P1 sens of \a this.<br>
3300  * For 1D cells, the returned field contains lengths.<br>
3301  * For 2D cells, the returned field contains areas.<br>
3302  * For 3D cells, the returned field contains volumes.
3303  * This method is useful to check "P1*" conservative interpolators.
3304  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3305  *         orientation, i.e. the volume is always positive.
3306  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3307  *          nodes and one time. The caller is to delete this array using decrRef() as
3308  *          it is no more needed.
3309  */
3310 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3311 {
3312   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3313   std::string name="MeasureOnNodeOfMesh_";
3314   name+=getName();
3315   int nbNodes=getNumberOfNodes();
3316   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3317   double cst=1./((double)getMeshDimension()+1.);
3318   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3319   array->alloc(nbNodes,1);
3320   double *valsToFill=array->getPointer();
3321   std::fill(valsToFill,valsToFill+nbNodes,0.);
3322   const double *values=tmp->getArray()->getConstPointer();
3323   MCAuto<DataArrayInt> da=DataArrayInt::New();
3324   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3325   getReverseNodalConnectivity(da,daInd);
3326   const int *daPtr=da->getConstPointer();
3327   const int *daIPtr=daInd->getConstPointer();
3328   for(int i=0;i<nbNodes;i++)
3329     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3330       valsToFill[i]+=cst*values[*cell];
3331   ret->setMesh(this);
3332   ret->setArray(array);
3333   return ret.retn();
3334 }
3335
3336 /*!
3337  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3338  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3339  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3340  * and are normalized.
3341  * <br> \a this can be either 
3342  * - a  2D mesh in 2D or 3D space or 
3343  * - an 1D mesh in 2D space.
3344  * 
3345  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3346  *          cells and one time. The caller is to delete this field using decrRef() as
3347  *          it is no more needed.
3348  *  \throw If the nodal connectivity of cells is not defined.
3349  *  \throw If the coordinates array is not set.
3350  *  \throw If the mesh dimension is not set.
3351  *  \throw If the mesh and space dimension is not as specified above.
3352  */
3353 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3354 {
3355   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3356     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3357   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3358   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3359   int nbOfCells=getNumberOfCells();
3360   int nbComp=getMeshDimension()+1;
3361   array->alloc(nbOfCells,nbComp);
3362   double *vals=array->getPointer();
3363   const int *connI=_nodal_connec_index->getConstPointer();
3364   const int *conn=_nodal_connec->getConstPointer();
3365   const double *coords=_coords->getConstPointer();
3366   if(getMeshDimension()==2)
3367     {
3368       if(getSpaceDimension()==3)
3369         {
3370           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3371           const double *locPtr=loc->getConstPointer();
3372           for(int i=0;i<nbOfCells;i++,vals+=3)
3373             {
3374               int offset=connI[i];
3375               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3376               double n=INTERP_KERNEL::norm<3>(vals);
3377               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3378             }
3379         }
3380       else
3381         {
3382           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3383           const double *isAbsPtr=isAbs->getArray()->begin();
3384           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3385             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3386         }
3387     }
3388   else//meshdimension==1
3389     {
3390       double tmp[2];
3391       for(int i=0;i<nbOfCells;i++)
3392         {
3393           int offset=connI[i];
3394           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3395           double n=INTERP_KERNEL::norm<2>(tmp);
3396           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3397           *vals++=-tmp[1];
3398           *vals++=tmp[0];
3399         }
3400     }
3401   ret->setArray(array);
3402   ret->setMesh(this);
3403   ret->synchronizeTimeWithSupport();
3404   return ret.retn();
3405 }
3406
3407 /*!
3408  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3409  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3410  * and are normalized.
3411  * <br> \a this can be either 
3412  * - a  2D mesh in 2D or 3D space or 
3413  * - an 1D mesh in 2D space.
3414  * 
3415  * This method avoids building explicitly a part of \a this mesh to perform the work.
3416  *  \param [in] begin - an array of cell ids of interest.
3417  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3418  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3419  *          cells and one time. The caller is to delete this field using decrRef() as
3420  *          it is no more needed.
3421  *  \throw If the nodal connectivity of cells is not defined.
3422  *  \throw If the coordinates array is not set.
3423  *  \throw If the mesh dimension is not set.
3424  *  \throw If the mesh and space dimension is not as specified above.
3425  *  \sa buildOrthogonalField()
3426  *
3427  *  \if ENABLE_EXAMPLES
3428  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3429  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3430  *  \endif
3431  */
3432 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3433 {
3434   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3435     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3436   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3437   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3438   std::size_t nbelems=std::distance(begin,end);
3439   int nbComp=getMeshDimension()+1;
3440   array->alloc((int)nbelems,nbComp);
3441   double *vals=array->getPointer();
3442   const int *connI=_nodal_connec_index->getConstPointer();
3443   const int *conn=_nodal_connec->getConstPointer();
3444   const double *coords=_coords->getConstPointer();
3445   if(getMeshDimension()==2)
3446     {
3447       if(getSpaceDimension()==3)
3448         {
3449           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3450           const double *locPtr=loc->getConstPointer();
3451           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3452             {
3453               int offset=connI[*i];
3454               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3455               double n=INTERP_KERNEL::norm<3>(vals);
3456               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3457             }
3458         }
3459       else
3460         {
3461           for(std::size_t i=0;i<nbelems;i++)
3462             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3463         }
3464     }
3465   else//meshdimension==1
3466     {
3467       double tmp[2];
3468       for(const int *i=begin;i!=end;i++)
3469         {
3470           int offset=connI[*i];
3471           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3472           double n=INTERP_KERNEL::norm<2>(tmp);
3473           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3474           *vals++=-tmp[1];
3475           *vals++=tmp[0];
3476         }
3477     }
3478   ret->setArray(array);
3479   ret->setMesh(this);
3480   ret->synchronizeTimeWithSupport();
3481   return ret.retn();
3482 }
3483
3484 /*!
3485  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3486  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3487  * and are \b not normalized.
3488  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3489  *          cells and one time. The caller is to delete this field using decrRef() as
3490  *          it is no more needed.
3491  *  \throw If the nodal connectivity of cells is not defined.
3492  *  \throw If the coordinates array is not set.
3493  *  \throw If \a this->getMeshDimension() != 1.
3494  *  \throw If \a this mesh includes cells of type other than SEG2.
3495  */
3496 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3497 {
3498   if(getMeshDimension()!=1)
3499     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3500   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3501     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3502   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3503   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3504   int nbOfCells=getNumberOfCells();
3505   int spaceDim=getSpaceDimension();
3506   array->alloc(nbOfCells,spaceDim);
3507   double *pt=array->getPointer();
3508   const double *coo=getCoords()->getConstPointer();
3509   std::vector<int> conn;
3510   conn.reserve(2);
3511   for(int i=0;i<nbOfCells;i++)
3512     {
3513       conn.resize(0);
3514       getNodeIdsOfCell(i,conn);
3515       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3516     }
3517   ret->setArray(array);
3518   ret->setMesh(this);
3519   ret->synchronizeTimeWithSupport();
3520   return ret.retn();
3521 }
3522
3523 /*!
3524  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3525  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3526  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3527  * from. If a result face is shared by two 3D cells, then the face in included twice in
3528  * the result mesh.
3529  *  \param [in] origin - 3 components of a point defining location of the plane.
3530  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3531  *         must be greater than 1e-6.
3532  *  \param [in] eps - half-thickness of the plane.
3533  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3534  *         producing correspondent 2D cells. The caller is to delete this array
3535  *         using decrRef() as it is no more needed.
3536  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3537  *         not share the node coordinates array with \a this mesh. The caller is to
3538  *         delete this mesh using decrRef() as it is no more needed.  
3539  *  \throw If the coordinates array is not set.
3540  *  \throw If the nodal connectivity of cells is not defined.
3541  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3542  *  \throw If magnitude of \a vec is less than 1e-6.
3543  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3544  *  \throw If \a this includes quadratic cells.
3545  */
3546 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3547 {
3548   checkFullyDefined();
3549   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3550     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3551   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3552   if(candidates->empty())
3553     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3554   std::vector<int> nodes;
3555   DataArrayInt *cellIds1D=0;
3556   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3557   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3558   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3559   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3560   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3561   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3562   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3563   revDesc2=0; revDescIndx2=0;
3564   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3565   revDesc1=0; revDescIndx1=0;
3566   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3567   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3568   //
3569   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3570   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3571     cut3DCurve[*it]=-1;
3572   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3573   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3574   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3575                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3576                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3577   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3578   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3579   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3580   if(cellIds2->empty())
3581     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3582   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3583   ret->setCoords(mDesc1->getCoords());
3584   ret->setConnectivity(conn,connI,true);
3585   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3586   return ret.retn();
3587 }
3588
3589 /*!
3590  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3591 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
3592 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3593 the result mesh.
3594  *  \param [in] origin - 3 components of a point defining location of the plane.
3595  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3596  *         must be greater than 1e-6.
3597  *  \param [in] eps - half-thickness of the plane.
3598  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3599  *         producing correspondent segments. The caller is to delete this array
3600  *         using decrRef() as it is no more needed.
3601  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3602  *         mesh in 3D space. This mesh does not share the node coordinates array with
3603  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3604  *         no more needed. 
3605  *  \throw If the coordinates array is not set.
3606  *  \throw If the nodal connectivity of cells is not defined.
3607  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3608  *  \throw If magnitude of \a vec is less than 1e-6.
3609  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3610  *  \throw If \a this includes quadratic cells.
3611  */
3612 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3613 {
3614   checkFullyDefined();
3615   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3616     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3617   MCAuto<DataArrayInt> candidates(getCellIdsCrossingPlane(origin,vec,eps));
3618   if(candidates->empty())
3619     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3620   std::vector<int> nodes;
3621   DataArrayInt *cellIds1D(0);
3622   MCAuto<MEDCouplingUMesh> subMesh(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3623   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3624   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
3625   MCAuto<MEDCouplingUMesh> mDesc1(subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3626   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3627   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3628   //
3629   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3630   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3631     cut3DCurve[*it]=-1;
3632   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3633   int ncellsSub=subMesh->getNumberOfCells();
3634   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3635   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3636                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3637                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3638   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3639   conn->alloc(0,1);
3640   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3641   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3642   for(int i=0;i<ncellsSub;i++)
3643     {
3644       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3645         {
3646           if(cut3DSurf[i].first!=-2)
3647             {
3648               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3649               connI->pushBackSilent(conn->getNumberOfTuples());
3650               cellIds2->pushBackSilent(i);
3651             }
3652           else
3653             {
3654               int cellId3DSurf=cut3DSurf[i].second;
3655               int offset=nodalI[cellId3DSurf]+1;
3656               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3657               for(int j=0;j<nbOfEdges;j++)
3658                 {
3659                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3660                   connI->pushBackSilent(conn->getNumberOfTuples());
3661                   cellIds2->pushBackSilent(cellId3DSurf);
3662                 }
3663             }
3664         }
3665     }
3666   if(cellIds2->empty())
3667     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3668   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3669   ret->setCoords(mDesc1->getCoords());
3670   ret->setConnectivity(conn,connI,true);
3671   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3672   return ret.retn();
3673 }
3674
3675 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::clipSingle3DCellByPlane(const double origin[3], const double vec[3], double eps) const
3676 {
3677   checkFullyDefined();
3678   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3679     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3680   if(getNumberOfCells()!=1)
3681     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works only on mesh containing exactly one cell !");
3682   //
3683   std::vector<int> nodes;
3684   findNodesOnPlane(origin,vec,eps,nodes);
3685   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());
3686   MCAuto<MEDCouplingUMesh> mDesc2(buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2));//meshDim==2 spaceDim==3
3687   revDesc2=0; revDescIndx2=0;
3688   MCAuto<MEDCouplingUMesh> mDesc1(mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3689   revDesc1=0; revDescIndx1=0;
3690   DataArrayInt *cellIds1D(0);
3691   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3692   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3693   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3694   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3695     cut3DCurve[*it]=-1;
3696   bool sameNbNodes;
3697   {
3698     int oldNbNodes(mDesc1->getNumberOfNodes());
3699     mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3700     sameNbNodes=(mDesc1->getNumberOfNodes()==oldNbNodes);
3701   }
3702   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3703   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->begin(),mDesc2->getNodalConnectivityIndex()->begin(),
3704                               mDesc1->getNodalConnectivity()->begin(),mDesc1->getNodalConnectivityIndex()->begin(),
3705                               desc1->begin(),descIndx1->begin(),cut3DSurf);
3706   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New());
3707   connI->pushBackSilent(0); conn->alloc(0,1);
3708   {
3709     MCAuto<DataArrayInt> cellIds2(DataArrayInt::New()); cellIds2->alloc(0,1);
3710     assemblyForSplitFrom3DSurf(cut3DSurf,desc2->begin(),descIndx2->begin(),conn,connI,cellIds2);
3711     if(cellIds2->empty())
3712       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3713   }
3714   std::vector<std::vector<int> > res;
3715   buildSubCellsFromCut(cut3DSurf,desc2->begin(),descIndx2->begin(),mDesc1->getCoords()->begin(),eps,res);
3716   std::size_t sz(res.size());
3717   if(res.size()==mDesc1->getNumberOfCells() && sameNbNodes)
3718     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane : cell is not clipped !");
3719   for(std::size_t i=0;i<sz;i++)
3720     {
3721       conn->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
3722       conn->insertAtTheEnd(res[i].begin(),res[i].end());
3723       connI->pushBackSilent(conn->getNumberOfTuples());
3724     }
3725   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
3726   ret->setCoords(mDesc1->getCoords());
3727   ret->setConnectivity(conn,connI,true);
3728   int nbCellsRet(ret->getNumberOfCells());
3729   //
3730   MCAuto<DataArrayDouble> vec2(DataArrayDouble::New()); vec2->alloc(1,3); std::copy(vec,vec+3,vec2->getPointer());
3731   MCAuto<MEDCouplingFieldDouble> ortho(ret->buildOrthogonalField());
3732   MCAuto<DataArrayDouble> ortho2(ortho->getArray()->selectByTupleIdSafeSlice(0,1,1));
3733   MCAuto<DataArrayDouble> dott(DataArrayDouble::Dot(ortho2,vec2));
3734   MCAuto<DataArrayDouble> ccm(ret->computeCellCenterOfMass());
3735   MCAuto<DataArrayDouble> occm;
3736   {
3737     MCAuto<DataArrayDouble> pt(DataArrayDouble::New()); pt->alloc(1,3); std::copy(origin,origin+3,pt->getPointer());
3738     occm=DataArrayDouble::Substract(ccm,pt);
3739   }
3740   vec2=DataArrayDouble::New(); vec2->alloc(nbCellsRet,3);
3741   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);
3742   MCAuto<DataArrayDouble> dott2(DataArrayDouble::Dot(occm,vec2));
3743   //
3744   const int *cPtr(ret->getNodalConnectivity()->begin()),*ciPtr(ret->getNodalConnectivityIndex()->begin());
3745   MCAuto<MEDCouplingUMesh> ret2(MEDCouplingUMesh::New("Clip3D",3));
3746   ret2->setCoords(mDesc1->getCoords());
3747   MCAuto<DataArrayInt> conn2(DataArrayInt::New()),conn2I(DataArrayInt::New());
3748   conn2I->pushBackSilent(0); conn2->alloc(0,1);
3749   std::vector<int> cell0(1,(int)INTERP_KERNEL::NORM_POLYHED);
3750   std::vector<int> cell1(1,(int)INTERP_KERNEL::NORM_POLYHED);
3751   if(dott->getIJ(0,0)>0)
3752     {
3753       cell0.insert(cell0.end(),cPtr+1,cPtr+ciPtr[1]);
3754       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell1,cell1.end()));
3755     }
3756   else
3757     {
3758       cell1.insert(cell1.end(),cPtr+1,cPtr+ciPtr[1]);
3759       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell0,cell0.end()));
3760     }
3761   for(int i=1;i<nbCellsRet;i++)
3762     {
3763       if(dott2->getIJ(i,0)<0)
3764         {
3765           if(ciPtr[i+1]-ciPtr[i]>=4)
3766             {
3767               cell0.push_back(-1);
3768               cell0.insert(cell0.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3769             }
3770         }
3771       else
3772         {
3773           if(ciPtr[i+1]-ciPtr[i]>=4)
3774             {
3775               cell1.push_back(-1);
3776               cell1.insert(cell1.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3777             }
3778         }
3779     }
3780   conn2->insertAtTheEnd(cell0.begin(),cell0.end());
3781   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3782   conn2->insertAtTheEnd(cell1.begin(),cell1.end());
3783   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3784   ret2->setConnectivity(conn2,conn2I,true);
3785   ret2->checkConsistencyLight();
3786   ret2->orientCorrectlyPolyhedrons();
3787   return ret2;
3788 }
3789
3790 /*!
3791  * Finds cells whose bounding boxes intersect a given plane.
3792  *  \param [in] origin - 3 components of a point defining location of the plane.
3793  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3794  *         must be greater than 1e-6.
3795  *  \param [in] eps - half-thickness of the plane.
3796  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3797  *         cells. The caller is to delete this array using decrRef() as it is no more
3798  *         needed.
3799  *  \throw If the coordinates array is not set.
3800  *  \throw If the nodal connectivity of cells is not defined.
3801  *  \throw If \a this->getSpaceDimension() != 3.
3802  *  \throw If magnitude of \a vec is less than 1e-6.
3803  *  \sa buildSlice3D()
3804  */
3805 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3806 {
3807   checkFullyDefined();
3808   if(getSpaceDimension()!=3)
3809     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3810   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3811   if(normm<1e-6)
3812     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3813   double vec2[3];
3814   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3815   double angle=acos(vec[2]/normm);
3816   MCAuto<DataArrayInt> cellIds;
3817   double bbox[6];
3818   if(angle>eps)
3819     {
3820       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3821       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3822       if(normm2/normm>1e-6)
3823         DataArrayDouble::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer(),coo->getPointer());
3824       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3825       mw->setCoords(coo);
3826       mw->getBoundingBox(bbox);
3827       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3828       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3829     }
3830   else
3831     {
3832       getBoundingBox(bbox);
3833       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3834       cellIds=getCellsInBoundingBox(bbox,eps);
3835     }
3836   return cellIds.retn();
3837 }
3838
3839 /*!
3840  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3841  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3842  * No consideration of coordinate is done by this method.
3843  * 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)
3844  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
3845  */
3846 bool MEDCouplingUMesh::isContiguous1D() const
3847 {
3848   if(getMeshDimension()!=1)
3849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3850   int nbCells=getNumberOfCells();
3851   if(nbCells<1)
3852     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3853   const int *connI(_nodal_connec_index->begin()),*conn(_nodal_connec->begin());
3854   int ref=conn[connI[0]+2];
3855   for(int i=1;i<nbCells;i++)
3856     {
3857       if(conn[connI[i]+1]!=ref)
3858         return false;
3859       ref=conn[connI[i]+2];
3860     }
3861   return true;
3862 }
3863
3864 /*!
3865  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3866  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3867  * \param pt reference point of the line
3868  * \param v normalized director vector of the line
3869  * \param eps max precision before throwing an exception
3870  * \param res output of size this->getNumberOfCells
3871  */
3872 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3873 {
3874   if(getMeshDimension()!=1)
3875     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3876   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3877     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3878   if(getSpaceDimension()!=3)
3879     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3880   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3881   const double *fPtr=f->getArray()->getConstPointer();
3882   double tmp[3];
3883   for(std::size_t i=0;i<getNumberOfCells();i++)
3884     {
3885       const double *tmp1=fPtr+3*i;
3886       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3887       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3888       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3889       double n1=INTERP_KERNEL::norm<3>(tmp);
3890       n1/=INTERP_KERNEL::norm<3>(tmp1);
3891       if(n1>eps)
3892         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3893     }
3894   const double *coo=getCoords()->getConstPointer();
3895   for(int i=0;i<getNumberOfNodes();i++)
3896     {
3897       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3898       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3899       res[i]=std::accumulate(tmp,tmp+3,0.);
3900     }
3901 }
3902
3903 /*!
3904  * 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. 
3905  * \a this is expected to be a mesh so that its space dimension is equal to its
3906  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3907  * 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).
3908  *
3909  * 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
3910  * 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).
3911  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3912  *
3913  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3914  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3915  *
3916  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3917  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3918  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3919  * \return the positive value of the distance.
3920  * \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
3921  * dimension - 1.
3922  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3923  */
3924 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3925 {
3926   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3927   if(meshDim!=spaceDim-1)
3928     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3929   if(meshDim!=2 && meshDim!=1)
3930     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3931   checkFullyDefined();
3932   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3933     { 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()); }
3934   DataArrayInt *ret1=0;
3935   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3936   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3937   MCAuto<DataArrayInt> ret1Safe(ret1);
3938   cellId=*ret1Safe->begin();
3939   return *ret0->begin();
3940 }
3941
3942 /*!
3943  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3944  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3945  * 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
3946  * 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).
3947  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3948  * 
3949  * \a this is expected to be a mesh so that its space dimension is equal to its
3950  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3951  * 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).
3952  *
3953  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3954  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3955  *
3956  * \param [in] pts the list of points in which each tuple represents a point
3957  * \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.
3958  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3959  * \throw if number of components of \a pts is not equal to the space dimension.
3960  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3961  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3962  */
3963 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3964 {
3965   if(!pts)
3966     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3967   pts->checkAllocated();
3968   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3969   if(meshDim!=spaceDim-1)
3970     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3971   if(meshDim!=2 && meshDim!=1)
3972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3973   if((int)pts->getNumberOfComponents()!=spaceDim)
3974     {
3975       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3976       throw INTERP_KERNEL::Exception(oss.str());
3977     }
3978   checkFullyDefined();
3979   int nbCells=getNumberOfCells();
3980   if(nbCells==0)
3981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3982   int nbOfPts=pts->getNumberOfTuples();
3983   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3984   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3985   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3986   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3987   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3988   const double *bbox(bboxArr->begin());
3989   switch(spaceDim)
3990   {
3991     case 3:
3992       {
3993         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3994         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3995           {
3996             double x=std::numeric_limits<double>::max();
3997             std::vector<int> elems;
3998             myTree.getMinDistanceOfMax(ptsPtr,x);
3999             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4000             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4001           }
4002         break;
4003       }
4004     case 2:
4005       {
4006         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4007         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4008           {
4009             double x=std::numeric_limits<double>::max();
4010             std::vector<int> elems;
4011             myTree.getMinDistanceOfMax(ptsPtr,x);
4012             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4013             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4014           }
4015         break;
4016       }
4017     default:
4018       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4019   }
4020   cellIds=ret1.retn();
4021   return ret0.retn();
4022 }
4023
4024 /// @cond INTERNAL
4025
4026 /// @endcond
4027
4028 /*!
4029  * Finds cells in contact with a ball (i.e. a point with precision). 
4030  * 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.
4031  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4032  *
4033  * \warning This method is suitable if the caller intends to evaluate only one
4034  *          point, for more points getCellsContainingPoints() is recommended as it is
4035  *          faster. 
4036  *  \param [in] pos - array of coordinates of the ball central point.
4037  *  \param [in] eps - ball radius.
4038  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4039  *         if there are no such cells.
4040  *  \throw If the coordinates array is not set.
4041  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4042  */
4043 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4044 {
4045   std::vector<int> elts;
4046   getCellsContainingPoint(pos,eps,elts);
4047   if(elts.empty())
4048     return -1;
4049   return elts.front();
4050 }
4051
4052 /*!
4053  * Finds cells in contact with a ball (i.e. a point with precision).
4054  * 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.
4055  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4056  * \warning This method is suitable if the caller intends to evaluate only one
4057  *          point, for more points getCellsContainingPoints() is recommended as it is
4058  *          faster. 
4059  *  \param [in] pos - array of coordinates of the ball central point.
4060  *  \param [in] eps - ball radius.
4061  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4062  *         before inserting ids.
4063  *  \throw If the coordinates array is not set.
4064  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4065  *
4066  *  \if ENABLE_EXAMPLES
4067  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4068  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4069  *  \endif
4070  */
4071 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4072 {
4073   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4074   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4075   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4076 }
4077
4078 /*!
4079  * Finds cells in contact with several balls (i.e. points with precision).
4080  * This method is an extension of getCellContainingPoint() and
4081  * getCellsContainingPoint() for the case of multiple points.
4082  * 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.
4083  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4084  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4085  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4086  *         this->getSpaceDimension() * \a nbOfPoints 
4087  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4088  *  \param [in] eps - radius of balls (i.e. the precision).
4089  *  \param [out] elts - vector returning ids of found cells.
4090  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4091  *         dividing cell ids in \a elts into groups each referring to one
4092  *         point. Its every element (except the last one) is an index pointing to the
4093  *         first id of a group of cells. For example cells in contact with the *i*-th
4094  *         point are described by following range of indices:
4095  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4096  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4097  *         Number of cells in contact with the *i*-th point is
4098  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4099  *  \throw If the coordinates array is not set.
4100  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4101  *
4102  *  \if ENABLE_EXAMPLES
4103  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4104  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4105  *  \endif
4106  */
4107 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4108                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4109 {
4110   int spaceDim=getSpaceDimension();
4111   int mDim=getMeshDimension();
4112   if(spaceDim==3)
4113     {
4114       if(mDim==3)
4115         {
4116           const double *coords=_coords->getConstPointer();
4117           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4118         }
4119       /*else if(mDim==2)
4120         {
4121
4122         }*/
4123       else
4124         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4125     }
4126   else if(spaceDim==2)
4127     {
4128       if(mDim==2)
4129         {
4130           const double *coords=_coords->getConstPointer();
4131           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4132         }
4133       else
4134         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4135     }
4136   else if(spaceDim==1)
4137     {
4138       if(mDim==1)
4139         {
4140           const double *coords=_coords->getConstPointer();
4141           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4142         }
4143       else
4144         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4145     }
4146   else
4147     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4148 }
4149
4150 /*!
4151  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4152  * least two its edges intersect each other anywhere except their extremities. An
4153  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4154  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4155  *         cleared before filling in.
4156  *  \param [in] eps - precision.
4157  *  \throw If \a this->getMeshDimension() != 2.
4158  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4159  */
4160 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4161 {
4162   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4163   if(getMeshDimension()!=2)
4164     throw INTERP_KERNEL::Exception(msg);
4165   int spaceDim=getSpaceDimension();
4166   if(spaceDim!=2 && spaceDim!=3)
4167     throw INTERP_KERNEL::Exception(msg);
4168   const int *conn=_nodal_connec->getConstPointer();
4169   const int *connI=_nodal_connec_index->getConstPointer();
4170   int nbOfCells=getNumberOfCells();
4171   std::vector<double> cell2DinS2;
4172   for(int i=0;i<nbOfCells;i++)
4173     {
4174       int offset=connI[i];
4175       int nbOfNodesForCell=connI[i+1]-offset-1;
4176       if(nbOfNodesForCell<=3)
4177         continue;
4178       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4179       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4180       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4181         cells.push_back(i);
4182       cell2DinS2.clear();
4183     }
4184 }
4185
4186 /*!
4187  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4188  *
4189  * 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.
4190  * 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.
4191  * 
4192  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4193  * This convex envelop is computed using Jarvis march algorithm.
4194  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4195  * 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)
4196  * 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.
4197  *
4198  * \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.
4199  * \sa MEDCouplingUMesh::colinearize2D
4200  */
4201 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4202 {
4203   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4204     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4205   checkFullyDefined();
4206   const double *coords=getCoords()->getConstPointer();
4207   int nbOfCells=getNumberOfCells();
4208   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4209   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4210   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4211   int *workIndexOut=nodalConnecIndexOut->getPointer();
4212   *workIndexOut=0;
4213   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4214   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4215   std::set<INTERP_KERNEL::NormalizedCellType> types;
4216   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4217   isChanged->alloc(0,1);
4218   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4219     {
4220       int pos=nodalConnecOut->getNumberOfTuples();
4221       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4222         isChanged->pushBackSilent(i);
4223       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4224       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4225     }
4226   if(isChanged->empty())
4227     return 0;
4228   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4229   _types=types;
4230   return isChanged.retn();
4231 }
4232
4233 /*!
4234  * This method is \b NOT const because it can modify \a this.
4235  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4236  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4237  * \param policy specifies the type of extrusion chosen:
4238  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4239  *   will be repeated to build each level
4240  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4241  *   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
4242  *   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
4243  *   arc.
4244  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4245  */
4246 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4247 {
4248   checkFullyDefined();
4249   mesh1D->checkFullyDefined();
4250   if(!mesh1D->isContiguous1D())
4251     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4252   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4253     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4254   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4255     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4256   if(mesh1D->getMeshDimension()!=1)
4257     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4258   bool isQuad=false;
4259   if(isPresenceOfQuadratic())
4260     {
4261       if(mesh1D->isFullyQuadratic())
4262         isQuad=true;
4263       else
4264         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4265     }
4266   int oldNbOfNodes(getNumberOfNodes());
4267   MCAuto<DataArrayDouble> newCoords;
4268   switch(policy)
4269   {
4270     case 0:
4271       {
4272         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4273         break;
4274       }
4275     case 1:
4276       {
4277         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4278         break;
4279       }
4280     default:
4281       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4282   }
4283   setCoords(newCoords);
4284   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4285   updateTime();
4286   return ret.retn();
4287 }
4288
4289
4290 /*!
4291  * Checks if \a this mesh is constituted by only quadratic cells.
4292  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4293  *  \throw If the coordinates array is not set.
4294  *  \throw If the nodal connectivity of cells is not defined.
4295  */
4296 bool MEDCouplingUMesh::isFullyQuadratic() const
4297 {
4298   checkFullyDefined();
4299   bool ret=true;
4300   int nbOfCells=getNumberOfCells();
4301   for(int i=0;i<nbOfCells && ret;i++)
4302     {
4303       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4304       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4305       ret=cm.isQuadratic();
4306     }
4307   return ret;
4308 }
4309
4310 /*!
4311  * Checks if \a this mesh includes any quadratic cell.
4312  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4313  *  \throw If the coordinates array is not set.
4314  *  \throw If the nodal connectivity of cells is not defined.
4315  */
4316 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4317 {
4318   checkFullyDefined();
4319   bool ret=false;
4320   int nbOfCells=getNumberOfCells();
4321   for(int i=0;i<nbOfCells && !ret;i++)
4322     {
4323       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4324       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4325       ret=cm.isQuadratic();
4326     }
4327   return ret;
4328 }
4329
4330 /*!
4331  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4332  * this mesh, it remains unchanged.
4333  *  \throw If the coordinates array is not set.
4334  *  \throw If the nodal connectivity of cells is not defined.
4335  */
4336 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4337 {
4338   checkFullyDefined();
4339   int nbOfCells(getNumberOfCells());
4340   int delta=0;
4341   const int *iciptr=_nodal_connec_index->begin();
4342   for(int i=0;i<nbOfCells;i++)
4343     {
4344       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4345       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4346       if(cm.isQuadratic())
4347         {
4348           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4349           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4350           if(!cml.isDynamic())
4351             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4352           else
4353             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4354         }
4355     }
4356   if(delta==0)
4357     return ;
4358   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4359   const int *icptr(_nodal_connec->begin());
4360   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
4361   newConnI->alloc(nbOfCells+1,1);
4362   int *ocptr(newConn->getPointer()),*ociptr(newConnI->getPointer());
4363   *ociptr=0;
4364   _types.clear();
4365   for(int i=0;i<nbOfCells;i++,ociptr++)
4366     {
4367       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4368       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4369       if(!cm.isQuadratic())
4370         {
4371           _types.insert(type);
4372           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4373           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4374         }
4375       else
4376         {
4377           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4378           _types.insert(typel);
4379           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4380           int newNbOfNodes=cml.getNumberOfNodes();
4381           if(cml.isDynamic())
4382             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4383           *ocptr++=(int)typel;
4384           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4385           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4386         }
4387     }
4388   setConnectivity(newConn,newConnI,false);
4389 }
4390
4391 /*!
4392  * This method converts all linear cell in \a this to quadratic one.
4393  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4394  * 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)
4395  * 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.
4396  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4397  * end of the existing coordinates.
4398  * 
4399  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4400  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4401  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4402  * 
4403  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4404  *
4405  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4406  */
4407 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4408 {
4409   DataArrayInt *conn=0,*connI=0;
4410   DataArrayDouble *coords=0;
4411   std::set<INTERP_KERNEL::NormalizedCellType> types;
4412   checkFullyDefined();
4413   MCAuto<DataArrayInt> ret,connSafe,connISafe;
4414   MCAuto<DataArrayDouble> coordsSafe;
4415   int meshDim=getMeshDimension();
4416   switch(conversionType)
4417   {
4418     case 0:
4419       switch(meshDim)
4420       {
4421         case 1:
4422           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4423           connSafe=conn; connISafe=connI; coordsSafe=coords;
4424           break;
4425         case 2:
4426           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4427           connSafe=conn; connISafe=connI; coordsSafe=coords;
4428           break;
4429         case 3:
4430           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4431           connSafe=conn; connISafe=connI; coordsSafe=coords;
4432           break;
4433         default:
4434           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4435       }
4436       break;
4437         case 1:
4438           {
4439             switch(meshDim)
4440             {
4441               case 1:
4442                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4443                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4444                 break;
4445               case 2:
4446                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4447                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4448                 break;
4449               case 3:
4450                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4451                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4452                 break;
4453               default:
4454                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4455             }
4456             break;
4457           }
4458         default:
4459           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4460   }
4461   setConnectivity(connSafe,connISafe,false);
4462   _types=types;
4463   setCoords(coordsSafe);
4464   return ret.retn();
4465 }
4466
4467 /*!
4468  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
4469  * so that the number of cells remains the same. Quadratic faces are converted to
4470  * polygons. This method works only for 2D meshes in
4471  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
4472  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
4473  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4474  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
4475  *         a polylinized edge constituting the input polygon.
4476  *  \throw If the coordinates array is not set.
4477  *  \throw If the nodal connectivity of cells is not defined.
4478  *  \throw If \a this->getMeshDimension() != 2.
4479  *  \throw If \a this->getSpaceDimension() != 2.
4480  */
4481 void MEDCouplingUMesh::tessellate2D(double eps)
4482 {
4483   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
4484   if(spaceDim!=2)
4485     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
4486   switch(meshDim)
4487     {
4488     case 1:
4489       return tessellate2DCurveInternal(eps);
4490     case 2:
4491       return tessellate2DInternal(eps);
4492     default:
4493       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
4494     }
4495 }
4496 /*!
4497  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
4498  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4499  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
4500  *         a sub-divided edge.
4501  *  \throw If the coordinates array is not set.
4502  *  \throw If the nodal connectivity of cells is not defined.
4503  *  \throw If \a this->getMeshDimension() != 1.
4504  *  \throw If \a this->getSpaceDimension() != 2.
4505  */
4506
4507 #if 0
4508 /*!
4509  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
4510  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
4511  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
4512  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
4513  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
4514  * This method can be seen as the opposite method of colinearize2D.
4515  * 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
4516  * to avoid to modify the numbering of existing nodes.
4517  *
4518  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
4519  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
4520  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
4521  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
4522  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
4523  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
4524  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
4525  *
4526  * \sa buildDescendingConnectivity2
4527  */
4528 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
4529                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
4530 {
4531   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
4532     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
4533   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
4534   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
4535     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
4536   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
4537     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
4538   //DataArrayInt *out0(0),*outi0(0);
4539   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
4540   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
4541   //out0s=out0s->buildUnique(); out0s->sort(true);
4542 }
4543 #endif
4544
4545
4546 /*!
4547  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
4548  * In addition, returns an array mapping new cells to old ones. <br>
4549  * This method typically increases the number of cells in \a this mesh
4550  * but the number of nodes remains \b unchanged.
4551  * That's why the 3D splitting policies
4552  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
4553  *  \param [in] policy - specifies a pattern used for splitting.
4554  * The semantic of \a policy is:
4555  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
4556  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
4557  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4558  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4559  *
4560  *
4561  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
4562  *          an id of old cell producing it. The caller is to delete this array using
4563  *         decrRef() as it is no more needed.
4564  *
4565  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
4566  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
4567  *          and \a this->getMeshDimension() != 3. 
4568  *  \throw If \a policy is not one of the four discussed above.
4569  *  \throw If the nodal connectivity of cells is not defined.
4570  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
4571  */
4572 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
4573 {
4574   switch(policy)
4575   {
4576     case 0:
4577       return simplexizePol0();
4578     case 1:
4579       return simplexizePol1();
4580     case (int) INTERP_KERNEL::PLANAR_FACE_5:
4581         return simplexizePlanarFace5();
4582     case (int) INTERP_KERNEL::PLANAR_FACE_6:
4583         return simplexizePlanarFace6();
4584     default:
4585       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)");
4586   }
4587 }
4588
4589 /*!
4590  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
4591  * - 1D: INTERP_KERNEL::NORM_SEG2
4592  * - 2D: INTERP_KERNEL::NORM_TRI3
4593  * - 3D: INTERP_KERNEL::NORM_TETRA4.
4594  *
4595  * This method is useful for users that need to use P1 field services as
4596  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
4597  * All these methods need mesh support containing only simplex cells.
4598  *  \return bool - \c true if there are only simplex cells in \a this mesh.
4599  *  \throw If the coordinates array is not set.
4600  *  \throw If the nodal connectivity of cells is not defined.
4601  *  \throw If \a this->getMeshDimension() < 1.
4602  */
4603 bool MEDCouplingUMesh::areOnlySimplexCells() const
4604 {
4605   checkFullyDefined();
4606   int mdim=getMeshDimension();
4607   if(mdim<1 || mdim>3)
4608     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
4609   int nbCells=getNumberOfCells();
4610   const int *conn=_nodal_connec->begin();
4611   const int *connI=_nodal_connec_index->begin();
4612   for(int i=0;i<nbCells;i++)
4613     {
4614       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4615       if(!cm.isSimplex())
4616         return false;
4617     }
4618   return true;
4619 }
4620
4621
4622
4623 /*!
4624  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
4625  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
4626  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
4627  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
4628  * so it can be useful to call mergeNodes() before calling this method.
4629  *  \throw If \a this->getMeshDimension() <= 1.
4630  *  \throw If the coordinates array is not set.
4631  *  \throw If the nodal connectivity of cells is not defined.
4632  */
4633 void MEDCouplingUMesh::convertDegeneratedCells()
4634 {
4635   checkFullyDefined();
4636   if(getMeshDimension()<=1)
4637     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4638   int nbOfCells=getNumberOfCells();
4639   if(nbOfCells<1)
4640     return ;
4641   int initMeshLgth=getNodalConnectivityArrayLen();
4642   int *conn=_nodal_connec->getPointer();
4643   int *index=_nodal_connec_index->getPointer();
4644   int posOfCurCell=0;
4645   int newPos=0;
4646   int lgthOfCurCell;
4647   for(int i=0;i<nbOfCells;i++)
4648     {
4649       lgthOfCurCell=index[i+1]-posOfCurCell;
4650       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4651       int newLgth;
4652       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4653                                                                                                      conn+newPos+1,newLgth);
4654       conn[newPos]=newType;
4655       newPos+=newLgth+1;
4656       posOfCurCell=index[i+1];
4657       index[i+1]=newPos;
4658     }
4659   if(newPos!=initMeshLgth)
4660     _nodal_connec->reAlloc(newPos);
4661   computeTypes();
4662 }
4663
4664 /*!
4665  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
4666  * A cell is considered to be oriented correctly if an angle between its
4667  * normal vector and a given vector is less than \c PI / \c 2.
4668  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4669  *         cells. 
4670  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4671  *         checked.
4672  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4673  *         is not cleared before filling in.
4674  *  \throw If \a this->getMeshDimension() != 2.
4675  *  \throw If \a this->getSpaceDimension() != 3.
4676  *
4677  *  \if ENABLE_EXAMPLES
4678  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4679  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4680  *  \endif
4681  */
4682 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
4683 {
4684   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4685     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4686   int nbOfCells=getNumberOfCells();
4687   const int *conn=_nodal_connec->begin();
4688   const int *connI=_nodal_connec_index->begin();
4689   const double *coordsPtr=_coords->begin();
4690   for(int i=0;i<nbOfCells;i++)
4691     {
4692       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4693       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4694         {
4695           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4696           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4697             cells.push_back(i);
4698         }
4699     }
4700 }
4701
4702 /*!
4703  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
4704  * considered to be oriented correctly if an angle between its normal vector and a
4705  * given vector is less than \c PI / \c 2. 
4706  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4707  *         cells. 
4708  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4709  *         checked.
4710  *  \throw If \a this->getMeshDimension() != 2.
4711  *  \throw If \a this->getSpaceDimension() != 3.
4712  *
4713  *  \if ENABLE_EXAMPLES
4714  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4715  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4716  *  \endif
4717  *
4718  *  \sa changeOrientationOfCells
4719  */
4720 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
4721 {
4722   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4723     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
4724   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4725   const int *connI(_nodal_connec_index->begin());
4726   const double *coordsPtr(_coords->begin());
4727   bool isModified(false);
4728   for(int i=0;i<nbOfCells;i++)
4729     {
4730       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4731       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4732         {
4733           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4734           bool isQuadratic(cm.isQuadratic());
4735           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4736             {
4737               isModified=true;
4738               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4739             }
4740         }
4741     }
4742   if(isModified)
4743     _nodal_connec->declareAsNew();
4744   updateTime();
4745 }
4746
4747 /*!
4748  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
4749  *
4750  * \sa orientCorrectly2DCells
4751  */
4752 void MEDCouplingUMesh::changeOrientationOfCells()
4753 {
4754   int mdim(getMeshDimension());
4755   if(mdim!=2 && mdim!=1)
4756     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
4757   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4758   const int *connI(_nodal_connec_index->begin());
4759   if(mdim==2)
4760     {//2D
4761       for(int i=0;i<nbOfCells;i++)
4762         {
4763           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4764           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4765           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4766         }
4767     }
4768   else
4769     {//1D
4770       for(int i=0;i<nbOfCells;i++)
4771         {
4772           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4773           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4774           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4775         }
4776     }
4777 }
4778
4779 /*!
4780  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
4781  * oriented facets. The normal vector of the facet should point out of the cell.
4782  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4783  *         is not cleared before filling in.
4784  *  \throw If \a this->getMeshDimension() != 3.
4785  *  \throw If \a this->getSpaceDimension() != 3.
4786  *  \throw If the coordinates array is not set.
4787  *  \throw If the nodal connectivity of cells is not defined.
4788  *
4789  *  \if ENABLE_EXAMPLES
4790  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4791  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4792  *  \endif
4793  */
4794 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
4795 {
4796   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4797     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
4798   int nbOfCells=getNumberOfCells();
4799   const int *conn=_nodal_connec->begin();
4800   const int *connI=_nodal_connec_index->begin();
4801   const double *coordsPtr=_coords->begin();
4802   for(int i=0;i<nbOfCells;i++)
4803     {
4804       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4805       if(type==INTERP_KERNEL::NORM_POLYHED)
4806         {
4807           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4808             cells.push_back(i);
4809         }
4810     }
4811 }
4812
4813 /*!
4814  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
4815  * out of the cell. 
4816  *  \throw If \a this->getMeshDimension() != 3.
4817  *  \throw If \a this->getSpaceDimension() != 3.
4818  *  \throw If the coordinates array is not set.
4819  *  \throw If the nodal connectivity of cells is not defined.
4820  *  \throw If the reparation fails.
4821  *
4822  *  \if ENABLE_EXAMPLES
4823  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4824  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4825  *  \endif
4826  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4827  */
4828 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
4829 {
4830   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4831     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
4832   int nbOfCells=getNumberOfCells();
4833   int *conn=_nodal_connec->getPointer();
4834   const int *connI=_nodal_connec_index->begin();
4835   const double *coordsPtr=_coords->begin();
4836   for(int i=0;i<nbOfCells;i++)
4837     {
4838       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4839       if(type==INTERP_KERNEL::NORM_POLYHED)
4840         {
4841           try
4842           {
4843               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4844                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4845           }
4846           catch(INTERP_KERNEL::Exception& e)
4847           {
4848               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
4849               throw INTERP_KERNEL::Exception(oss.str());
4850           }
4851         }
4852     }
4853   updateTime();
4854 }
4855
4856 /*!
4857  * This method invert orientation of all cells in \a this. 
4858  * After calling this method the absolute value of measure of cells in \a this are the same than before calling.
4859  * This method only operates on the connectivity so coordinates are not touched at all.
4860  */
4861 void MEDCouplingUMesh::invertOrientationOfAllCells()
4862 {
4863   checkConnectivityFullyDefined();
4864   std::set<INTERP_KERNEL::NormalizedCellType> gts(getAllGeoTypes());
4865   int *conn(_nodal_connec->getPointer());
4866   const int *conni(_nodal_connec_index->begin());
4867   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator gt=gts.begin();gt!=gts.end();gt++)
4868     {
4869       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::OrientationInverter> oi(INTERP_KERNEL::OrientationInverter::BuildInstanceFrom(*gt));
4870       MCAuto<DataArrayInt> cwt(giveCellsWithType(*gt));
4871       for(const int *it=cwt->begin();it!=cwt->end();it++)
4872         oi->operate(conn+conni[*it]+1,conn+conni[*it+1]);
4873     }
4874   updateTime();
4875 }
4876
4877 /*!
4878  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
4879  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
4880  * according to which the first facet of the cell should be oriented to have the normal vector
4881  * pointing out of cell.
4882  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
4883  *         cells. The caller is to delete this array using decrRef() as it is no more
4884  *         needed. 
4885  *  \throw If \a this->getMeshDimension() != 3.
4886  *  \throw If \a this->getSpaceDimension() != 3.
4887  *  \throw If the coordinates array is not set.
4888  *  \throw If the nodal connectivity of cells is not defined.
4889  *
4890  *  \if ENABLE_EXAMPLES
4891  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
4892  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
4893  *  \endif
4894  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4895  */
4896 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
4897 {
4898   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
4899   if(getMeshDimension()!=3)
4900     throw INTERP_KERNEL::Exception(msg);
4901   int spaceDim=getSpaceDimension();
4902   if(spaceDim!=3)
4903     throw INTERP_KERNEL::Exception(msg);
4904   //
4905   int nbOfCells=getNumberOfCells();
4906   int *conn=_nodal_connec->getPointer();
4907   const int *connI=_nodal_connec_index->begin();
4908   const double *coo=getCoords()->begin();
4909   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
4910   for(int i=0;i<nbOfCells;i++)
4911     {
4912       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4913       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
4914         {
4915           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
4916             {
4917               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4918               cells->pushBackSilent(i);
4919             }
4920         }
4921     }
4922   return cells.retn();
4923 }
4924
4925 /*!
4926  * This method is a faster method to correct orientation of all 3D cells in \a this.
4927  * 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.
4928  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
4929  * 
4930  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
4931  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
4932  */
4933 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
4934 {
4935   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4936     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
4937   int nbOfCells=getNumberOfCells();
4938   int *conn=_nodal_connec->getPointer();
4939   const int *connI=_nodal_connec_index->begin();
4940   const double *coordsPtr=_coords->begin();
4941   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4942   for(int i=0;i<nbOfCells;i++)
4943     {
4944       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4945       switch(type)
4946       {
4947         case INTERP_KERNEL::NORM_TETRA4:
4948           {
4949             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4950               {
4951                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
4952                 ret->pushBackSilent(i);
4953               }
4954             break;
4955           }
4956         case INTERP_KERNEL::NORM_PYRA5:
4957           {
4958             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4959               {
4960                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
4961                 ret->pushBackSilent(i);
4962               }
4963             break;
4964           }
4965         case INTERP_KERNEL::NORM_PENTA6:
4966         case INTERP_KERNEL::NORM_HEXA8:
4967         case INTERP_KERNEL::NORM_HEXGP12:
4968           {
4969             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4970               {
4971                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4972                 ret->pushBackSilent(i);
4973               }
4974             break;
4975           }
4976         case INTERP_KERNEL::NORM_POLYHED:
4977           {
4978             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4979               {
4980                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4981                 ret->pushBackSilent(i);
4982               }
4983             break;
4984           }
4985         default:
4986           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 !");
4987       }
4988     }
4989   updateTime();
4990   return ret.retn();
4991 }
4992
4993 /*!
4994  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
4995  * If it is not the case an exception will be thrown.
4996  * This method is fast because the first cell of \a this is used to compute the plane.
4997  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
4998  * \param pos output of size at least 3 used to store a point owned of searched plane.
4999  */
5000 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5001 {
5002   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5003     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5004   const int *conn=_nodal_connec->begin();
5005   const int *connI=_nodal_connec_index->begin();
5006   const double *coordsPtr=_coords->begin();
5007   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5008   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5009 }
5010
5011 /*!
5012  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5013  * cells. Currently cells of the following types are treated:
5014  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5015  * For a cell of other type an exception is thrown.
5016  * Space dimension of a 2D mesh can be either 2 or 3.
5017  * The Edge Ratio of a cell \f$t\f$ is: 
5018  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5019  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5020  *  the smallest edge lengths of \f$t\f$.
5021  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5022  *          cells and one time, lying on \a this mesh. The caller is to delete this
5023  *          field using decrRef() as it is no more needed. 
5024  *  \throw If the coordinates array is not set.
5025  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5026  *  \throw If the connectivity data array has more than one component.
5027  *  \throw If the connectivity data array has a named component.
5028  *  \throw If the connectivity index data array has more than one component.
5029  *  \throw If the connectivity index data array has a named component.
5030  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5031  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5032  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5033  */
5034 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
5035 {
5036   checkConsistencyLight();
5037   int spaceDim=getSpaceDimension();
5038   int meshDim=getMeshDimension();
5039   if(spaceDim!=2 && spaceDim!=3)
5040     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5041   if(meshDim!=2 && meshDim!=3)
5042     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5043   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5044   ret->setMesh(this);
5045   int nbOfCells=getNumberOfCells();
5046   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5047   arr->alloc(nbOfCells,1);
5048   double *pt=arr->getPointer();
5049   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5050   const int *conn=_nodal_connec->begin();
5051   const int *connI=_nodal_connec_index->begin();
5052   const double *coo=_coords->begin();
5053   double tmp[12];
5054   for(int i=0;i<nbOfCells;i++,pt++)
5055     {
5056       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5057       switch(t)
5058       {
5059         case INTERP_KERNEL::NORM_TRI3:
5060           {
5061             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5062             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5063             break;
5064           }
5065         case INTERP_KERNEL::NORM_QUAD4:
5066           {
5067             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5068             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5069             break;
5070           }
5071         case INTERP_KERNEL::NORM_TETRA4:
5072           {
5073             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5074             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5075             break;
5076           }
5077         default:
5078           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5079       }
5080       conn+=connI[i+1]-connI[i];
5081     }
5082   ret->setName("EdgeRatio");
5083   ret->synchronizeTimeWithSupport();
5084   return ret.retn();
5085 }
5086
5087 /*!
5088  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5089  * cells. Currently cells of the following types are treated:
5090  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5091  * For a cell of other type an exception is thrown.
5092  * Space dimension of a 2D mesh can be either 2 or 3.
5093  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5094  *          cells and one time, lying on \a this mesh. The caller is to delete this
5095  *          field using decrRef() as it is no more needed. 
5096  *  \throw If the coordinates array is not set.
5097  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5098  *  \throw If the connectivity data array has more than one component.
5099  *  \throw If the connectivity data array has a named component.
5100  *  \throw If the connectivity index data array has more than one component.
5101  *  \throw If the connectivity index data array has a named component.
5102  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5103  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5104  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5105  */
5106 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
5107 {
5108   checkConsistencyLight();
5109   int spaceDim=getSpaceDimension();
5110   int meshDim=getMeshDimension();
5111   if(spaceDim!=2 && spaceDim!=3)
5112     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5113   if(meshDim!=2 && meshDim!=3)
5114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5115   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5116   ret->setMesh(this);
5117   int nbOfCells=getNumberOfCells();
5118   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5119   arr->alloc(nbOfCells,1);
5120   double *pt=arr->getPointer();
5121   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5122   const int *conn=_nodal_connec->begin();
5123   const int *connI=_nodal_connec_index->begin();
5124   const double *coo=_coords->begin();
5125   double tmp[12];
5126   for(int i=0;i<nbOfCells;i++,pt++)
5127     {
5128       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5129       switch(t)
5130       {
5131         case INTERP_KERNEL::NORM_TRI3:
5132           {
5133             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5134             *pt=INTERP_KERNEL::triAspectRatio(tmp);
5135             break;
5136           }
5137         case INTERP_KERNEL::NORM_QUAD4:
5138           {
5139             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5140             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5141             break;
5142           }
5143         case INTERP_KERNEL::NORM_TETRA4:
5144           {
5145             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5146             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5147             break;
5148           }
5149         default:
5150           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5151       }
5152       conn+=connI[i+1]-connI[i];
5153     }
5154   ret->setName("AspectRatio");
5155   ret->synchronizeTimeWithSupport();
5156   return ret.retn();
5157 }
5158
5159 /*!
5160  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
5161  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
5162  * in 3D space. Currently only cells of the following types are
5163  * treated: INTERP_KERNEL::NORM_QUAD4.
5164  * For a cell of other type an exception is thrown.
5165  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
5166  * Defining
5167  * \f$t=\vec{da}\times\vec{ab}\f$,
5168  * \f$u=\vec{ab}\times\vec{bc}\f$
5169  * \f$v=\vec{bc}\times\vec{cd}\f$
5170  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
5171  *  \f[
5172  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
5173  *  \f]
5174  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5175  *          cells and one time, lying on \a this mesh. The caller is to delete this
5176  *          field using decrRef() as it is no more needed. 
5177  *  \throw If the coordinates array is not set.
5178  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5179  *  \throw If the connectivity data array has more than one component.
5180  *  \throw If the connectivity data array has a named component.
5181  *  \throw If the connectivity index data array has more than one component.
5182  *  \throw If the connectivity index data array has a named component.
5183  *  \throw If \a this->getMeshDimension() != 2.
5184  *  \throw If \a this->getSpaceDimension() != 3.
5185  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5186  */
5187 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
5188 {
5189   checkConsistencyLight();
5190   int spaceDim=getSpaceDimension();
5191   int meshDim=getMeshDimension();
5192   if(spaceDim!=3)
5193     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5194   if(meshDim!=2)
5195     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5196   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5197   ret->setMesh(this);
5198   int nbOfCells=getNumberOfCells();
5199   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5200   arr->alloc(nbOfCells,1);
5201   double *pt=arr->getPointer();
5202   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5203   const int *conn=_nodal_connec->begin();
5204   const int *connI=_nodal_connec_index->begin();
5205   const double *coo=_coords->begin();
5206   double tmp[12];
5207   for(int i=0;i<nbOfCells;i++,pt++)
5208     {
5209       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5210       switch(t)
5211       {
5212         case INTERP_KERNEL::NORM_QUAD4:
5213           {
5214             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5215             *pt=INTERP_KERNEL::quadWarp(tmp);
5216             break;
5217           }
5218         default:
5219           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5220       }
5221       conn+=connI[i+1]-connI[i];
5222     }
5223   ret->setName("Warp");
5224   ret->synchronizeTimeWithSupport();
5225   return ret.retn();
5226 }
5227
5228
5229 /*!
5230  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
5231  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
5232  * treated: INTERP_KERNEL::NORM_QUAD4.
5233  * The skew is computed as follow for a quad with points (a,b,c,d): let
5234  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
5235  * then the skew is computed as:
5236  *  \f[
5237  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
5238  *  \f]
5239  *
5240  * For a cell of other type an exception is thrown.
5241  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5242  *          cells and one time, lying on \a this mesh. The caller is to delete this
5243  *          field using decrRef() as it is no more needed. 
5244  *  \throw If the coordinates array is not set.
5245  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5246  *  \throw If the connectivity data array has more than one component.
5247  *  \throw If the connectivity data array has a named component.
5248  *  \throw If the connectivity index data array has more than one component.
5249  *  \throw If the connectivity index data array has a named component.
5250  *  \throw If \a this->getMeshDimension() != 2.
5251  *  \throw If \a this->getSpaceDimension() != 3.
5252  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5253  */
5254 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
5255 {
5256   checkConsistencyLight();
5257   int spaceDim=getSpaceDimension();
5258   int meshDim=getMeshDimension();
5259   if(spaceDim!=3)
5260     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5261   if(meshDim!=2)
5262     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5263   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5264   ret->setMesh(this);
5265   int nbOfCells=getNumberOfCells();
5266   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5267   arr->alloc(nbOfCells,1);
5268   double *pt=arr->getPointer();
5269   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5270   const int *conn=_nodal_connec->begin();
5271   const int *connI=_nodal_connec_index->begin();
5272   const double *coo=_coords->begin();
5273   double tmp[12];
5274   for(int i=0;i<nbOfCells;i++,pt++)
5275     {
5276       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5277       switch(t)
5278       {
5279         case INTERP_KERNEL::NORM_QUAD4:
5280           {
5281             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5282             *pt=INTERP_KERNEL::quadSkew(tmp);
5283             break;
5284           }
5285         default:
5286           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5287       }
5288       conn+=connI[i+1]-connI[i];
5289     }
5290   ret->setName("Skew");
5291   ret->synchronizeTimeWithSupport();
5292   return ret.retn();
5293 }
5294
5295 /*!
5296  * 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.
5297  *
5298  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
5299  *
5300  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
5301  */
5302 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
5303 {
5304   checkConsistencyLight();
5305   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
5306   ret->setMesh(this);
5307   std::set<INTERP_KERNEL::NormalizedCellType> types;
5308   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
5309   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
5310   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
5311   arr->alloc(nbCells,1);
5312   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
5313     {
5314       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
5315       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
5316       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
5317     }
5318   ret->setArray(arr);
5319   ret->setName("Diameter");
5320   return ret.retn();
5321 }
5322
5323 /*!
5324  * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax).
5325  * 
5326  * \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)
5327  *                         For all other cases this input parameter is ignored.
5328  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5329  * 
5330  * \throw If \a this is not fully set (coordinates and connectivity).
5331  * \throw If a cell in \a this has no valid nodeId.
5332  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5333  */
5334 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
5335 {
5336   int mDim(getMeshDimension()),sDim(getSpaceDimension());
5337   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.
5338     return getBoundingBoxForBBTreeFast();
5339   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
5340     {
5341       bool presenceOfQuadratic(false);
5342       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
5343         {
5344           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
5345           if(cm.isQuadratic())
5346             presenceOfQuadratic=true;
5347         }
5348       if(!presenceOfQuadratic)
5349         return getBoundingBoxForBBTreeFast();
5350       if(mDim==2 && sDim==2)
5351         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
5352       else
5353         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
5354     }
5355   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) !");
5356 }
5357
5358 /*!
5359  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
5360  * So meshes having quadratic cells the computed bounding boxes can be invalid !
5361  * 
5362  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5363  * 
5364  * \throw If \a this is not fully set (coordinates and connectivity).
5365  * \throw If a cell in \a this has no valid nodeId.
5366  */
5367 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
5368 {
5369   checkFullyDefined();
5370   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
5371   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5372   double *bbox(ret->getPointer());
5373   for(int i=0;i<nbOfCells*spaceDim;i++)
5374     {
5375       bbox[2*i]=std::numeric_limits<double>::max();
5376       bbox[2*i+1]=-std::numeric_limits<double>::max();
5377     }
5378   const double *coordsPtr(_coords->begin());
5379   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5380   for(int i=0;i<nbOfCells;i++)
5381     {
5382       int offset=connI[i]+1;
5383       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
5384       for(int j=0;j<nbOfNodesForCell;j++)
5385         {
5386           int nodeId=conn[offset+j];
5387           if(nodeId>=0 && nodeId<nbOfNodes)
5388             {
5389               for(int k=0;k<spaceDim;k++)
5390                 {
5391                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5392                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5393                 }
5394               kk++;
5395             }
5396         }
5397       if(kk==0)
5398         {
5399           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
5400           throw INTERP_KERNEL::Exception(oss.str());
5401         }
5402     }
5403   return ret.retn();
5404 }
5405
5406 /*!
5407  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
5408  * useful for 2D meshes having quadratic cells
5409  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5410  * the two extremities of the arc of circle).
5411  * 
5412  * \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)
5413  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5414  * \throw If \a this is not fully defined.
5415  * \throw If \a this is not a mesh with meshDimension equal to 2.
5416  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5417  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
5418  */
5419 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
5420 {
5421   checkFullyDefined();
5422   INTERP_KERNEL::QuadraticPlanarArcDetectionPrecision arcPrec(arcDetEps);
5423
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       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5436       INTERP_KERNEL::QuadraticPolygon *pol(0);
5437       for(int j=0;j<sz;j++)
5438         {
5439           int nodeId(conn[*connI+1+j]);
5440           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5441         }
5442       if(!cm.isQuadratic())
5443         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
5444       else
5445         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
5446       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
5447       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
5448     }
5449   return ret.retn();
5450 }
5451
5452 /*!
5453  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
5454  * useful for 2D meshes having quadratic cells
5455  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5456  * the two extremities of the arc of circle).
5457  * 
5458  * \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)
5459  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5460  * \throw If \a this is not fully defined.
5461  * \throw If \a this is not a mesh with meshDimension equal to 1.
5462  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5463  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5464  */
5465 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
5466 {
5467   checkFullyDefined();
5468   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5469   if(spaceDim!=2 || mDim!=1)
5470     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!");
5471   INTERP_KERNEL::QuadraticPlanarArcDetectionPrecision arcPrec(arcDetEps);
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       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5481       INTERP_KERNEL::Edge *edge(0);
5482       for(int j=0;j<sz;j++)
5483         {
5484           int nodeId(conn[*connI+1+j]);
5485           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5486         }
5487       if(!cm.isQuadratic())
5488         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
5489       else
5490         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
5491       const INTERP_KERNEL::Bounds& b(edge->getBounds());
5492       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
5493     }
5494   return ret.retn();
5495 }
5496
5497 /// @cond INTERNAL
5498
5499 namespace MEDCouplingImpl
5500 {
5501   class ConnReader
5502   {
5503   public:
5504     ConnReader(const int *c, int val):_conn(c),_val(val) { }
5505     bool operator() (const int& pos) { return _conn[pos]!=_val; }
5506   private:
5507     const int *_conn;
5508     int _val;
5509   };
5510
5511   class ConnReader2
5512   {
5513   public:
5514     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5515     bool operator() (const int& pos) { return _conn[pos]==_val; }
5516   private:
5517     const int *_conn;
5518     int _val;
5519   };
5520 }
5521
5522 /// @endcond
5523
5524 /*!
5525  * This method expects that \a this is sorted by types. If not an exception will be thrown.
5526  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5527  * \a this is composed in cell types.
5528  * The returned array is of size 3*n where n is the number of different types present in \a this. 
5529  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
5530  * This parameter is kept only for compatibility with other methode listed above.
5531  */
5532 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
5533 {
5534   checkConnectivityFullyDefined();
5535   const int *conn=_nodal_connec->begin();
5536   const int *connI=_nodal_connec_index->begin();
5537   const int *work=connI;
5538   int nbOfCells=getNumberOfCells();
5539   std::size_t n=getAllGeoTypes().size();
5540   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
5541   std::set<INTERP_KERNEL::NormalizedCellType> types;
5542   for(std::size_t i=0;work!=connI+nbOfCells;i++)
5543     {
5544       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5545       if(types.find(typ)!=types.end())
5546         {
5547           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5548           oss << " is not contiguous !";
5549           throw INTERP_KERNEL::Exception(oss.str());
5550         }
5551       types.insert(typ);
5552       ret[3*i]=typ;
5553       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
5554       ret[3*i+1]=(int)std::distance(work,work2);
5555       work=work2;
5556     }
5557   return ret;
5558 }
5559
5560 /*!
5561  * This method is used to check that this has contiguous cell type in same order than described in \a code.
5562  * only for types cell, type node is not managed.
5563  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
5564  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5565  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5566  * If 2 or more same geometric type is in \a code and exception is thrown too.
5567  *
5568  * This method firstly checks
5569  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5570  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5571  * an exception is thrown too.
5572  * 
5573  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
5574  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
5575  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5576  */
5577 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
5578 {
5579   if(code.empty())
5580     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5581   std::size_t sz=code.size();
5582   std::size_t n=sz/3;
5583   if(sz%3!=0)
5584     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5585   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5586   int nb=0;
5587   bool isNoPflUsed=true;
5588   for(std::size_t i=0;i<n;i++)
5589     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5590       {
5591         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5592         nb+=code[3*i+1];
5593         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5594           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5595         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
5596       }
5597   if(types.size()!=n)
5598     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5599   if(isNoPflUsed)
5600     {
5601       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5602         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5603       if(types.size()==_types.size())
5604         return 0;
5605     }
5606   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5607   ret->alloc(nb,1);
5608   int *retPtr=ret->getPointer();
5609   const int *connI=_nodal_connec_index->begin();
5610   const int *conn=_nodal_connec->begin();
5611   int nbOfCells=getNumberOfCells();
5612   const int *i=connI;
5613   int kk=0;
5614   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5615     {
5616       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
5617       int offset=(int)std::distance(connI,i);
5618       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
5619       int nbOfCellsOfCurType=(int)std::distance(i,j);
5620       if(code[3*kk+2]==-1)
5621         for(int k=0;k<nbOfCellsOfCurType;k++)
5622           *retPtr++=k+offset;
5623       else
5624         {
5625           int idInIdsPerType=code[3*kk+2];
5626           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
5627             {
5628               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
5629               if(zePfl)
5630                 {
5631                   zePfl->checkAllocated();
5632                   if(zePfl->getNumberOfComponents()==1)
5633                     {
5634                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
5635                         {
5636                           if(*k>=0 && *k<nbOfCellsOfCurType)
5637                             *retPtr=(*k)+offset;
5638                           else
5639                             {
5640                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
5641                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
5642                               throw INTERP_KERNEL::Exception(oss.str());
5643                             }
5644                         }
5645                     }
5646                   else
5647                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
5648                 }
5649               else
5650                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
5651             }
5652           else
5653             {
5654               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
5655               oss << " should be in [0," << idsPerType.size() << ") !";
5656               throw INTERP_KERNEL::Exception(oss.str());
5657             }
5658         }
5659       i=j;
5660     }
5661   return ret.retn();
5662 }
5663
5664 /*!
5665  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
5666  * 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.
5667  * 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.
5668  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
5669  * 
5670  * \param [in] profile
5671  * \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.
5672  * \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,
5673  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5674  * \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.
5675  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5676  * \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
5677  */
5678 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
5679 {
5680   if(!profile)
5681     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
5682   if(profile->getNumberOfComponents()!=1)
5683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5684   checkConnectivityFullyDefined();
5685   const int *conn=_nodal_connec->begin();
5686   const int *connI=_nodal_connec_index->begin();
5687   int nbOfCells=getNumberOfCells();
5688   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5689   std::vector<int> typeRangeVals(1);
5690   for(const int *i=connI;i!=connI+nbOfCells;)
5691     {
5692       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5693       if(std::find(types.begin(),types.end(),curType)!=types.end())
5694         {
5695           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5696         }
5697       types.push_back(curType);
5698       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5699       typeRangeVals.push_back((int)std::distance(connI,i));
5700     }
5701   //
5702   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5703   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5704   MCAuto<DataArrayInt> tmp0=castArr;
5705   MCAuto<DataArrayInt> tmp1=rankInsideCast;
5706   MCAuto<DataArrayInt> tmp2=castsPresent;
5707   //
5708   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5709   code.resize(3*nbOfCastsFinal);
5710   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
5711   std::vector< MCAuto<DataArrayInt> > idsPerType2;
5712   for(int i=0;i<nbOfCastsFinal;i++)
5713     {
5714       int castId=castsPresent->getIJ(i,0);
5715       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
5716       idsInPflPerType2.push_back(tmp3);
5717       code[3*i]=(int)types[castId];
5718       code[3*i+1]=tmp3->getNumberOfTuples();
5719       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->begin(),tmp3->begin()+tmp3->getNumberOfTuples());
5720       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
5721         {
5722           tmp4->copyStringInfoFrom(*profile);
5723           idsPerType2.push_back(tmp4);
5724           code[3*i+2]=(int)idsPerType2.size()-1;
5725         }
5726       else
5727         {
5728           code[3*i+2]=-1;
5729         }
5730     }
5731   std::size_t sz2=idsInPflPerType2.size();
5732   idsInPflPerType.resize(sz2);
5733   for(std::size_t i=0;i<sz2;i++)
5734     {
5735       DataArrayInt *locDa=idsInPflPerType2[i];
5736       locDa->incrRef();
5737       idsInPflPerType[i]=locDa;
5738     }
5739   std::size_t sz=idsPerType2.size();
5740   idsPerType.resize(sz);
5741   for(std::size_t i=0;i<sz;i++)
5742     {
5743       DataArrayInt *locDa=idsPerType2[i];
5744       locDa->incrRef();
5745       idsPerType[i]=locDa;
5746     }
5747 }
5748
5749 /*!
5750  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5751  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5752  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5753  * 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.
5754  */
5755 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
5756 {
5757   checkFullyDefined();
5758   nM1LevMesh->checkFullyDefined();
5759   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5760     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5761   if(_coords!=nM1LevMesh->getCoords())
5762     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5763   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
5764   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
5765   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5766   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5767   desc->transformWithIndArr(ret0->begin(),ret0->begin()+ret0->getNbOfElems());
5768   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5769   tmp->setConnectivity(tmp0,tmp1);
5770   tmp->renumberCells(ret0->begin(),false);
5771   revDesc=tmp->getNodalConnectivity();
5772   revDescIndx=tmp->getNodalConnectivityIndex();
5773   DataArrayInt *ret=0;
5774   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5775     {
5776       int tmp2;
5777       ret->getMaxValue(tmp2);
5778       ret->decrRef();
5779       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5780       throw INTERP_KERNEL::Exception(oss.str());
5781     }
5782   nM1LevMeshIds=ret;
5783   //
5784   revDesc->incrRef();
5785   revDescIndx->incrRef();
5786   ret1->incrRef();
5787   ret0->incrRef();
5788   meshnM1Old2New=ret0;
5789   return ret1;
5790 }
5791
5792 /*!
5793  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
5794  * necessary for writing the mesh to MED file. Additionally returns a permutation array
5795  * in "Old to New" mode.
5796  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
5797  *          this array using decrRef() as it is no more needed.
5798  *  \throw If the nodal connectivity of cells is not defined.
5799  */
5800 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
5801 {
5802   checkConnectivityFullyDefined();
5803   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
5804   renumberCells(ret->begin(),false);
5805   return ret.retn();
5806 }
5807
5808 /*!
5809  * This methods checks that cells are sorted by their types.
5810  * This method makes asumption (no check) that connectivity is correctly set before calling.
5811  */
5812 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5813 {
5814   checkFullyDefined();
5815   const int *conn=_nodal_connec->begin();
5816   const int *connI=_nodal_connec_index->begin();
5817   int nbOfCells=getNumberOfCells();
5818   std::set<INTERP_KERNEL::NormalizedCellType> types;
5819   for(const int *i=connI;i!=connI+nbOfCells;)
5820     {
5821       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5822       if(types.find(curType)!=types.end())
5823         return false;
5824       types.insert(curType);
5825       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5826     }
5827   return true;
5828 }
5829
5830 /*!
5831  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
5832  * The geometric type order is specified by MED file.
5833  * 
5834  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
5835  */
5836 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
5837 {
5838   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5839 }
5840
5841 /*!
5842  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5843  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
5844  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
5845  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
5846  */
5847 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5848 {
5849   checkFullyDefined();
5850   const int *conn=_nodal_connec->begin();
5851   const int *connI=_nodal_connec_index->begin();
5852   int nbOfCells=getNumberOfCells();
5853   if(nbOfCells==0)
5854     return true;
5855   int lastPos=-1;
5856   std::set<INTERP_KERNEL::NormalizedCellType> sg;
5857   for(const int *i=connI;i!=connI+nbOfCells;)
5858     {
5859       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5860       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
5861       if(isTypeExists!=orderEnd)
5862         {
5863           int pos=(int)std::distance(orderBg,isTypeExists);
5864           if(pos<=lastPos)
5865             return false;
5866           lastPos=pos;
5867           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5868         }
5869       else
5870         {
5871           if(sg.find(curType)==sg.end())
5872             {
5873               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5874               sg.insert(curType);
5875             }
5876           else
5877             return false;
5878         }
5879     }
5880   return true;
5881 }
5882
5883 /*!
5884  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5885  * 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
5886  * 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'.
5887  */
5888 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
5889 {
5890   checkConnectivityFullyDefined();
5891   int nbOfCells=getNumberOfCells();
5892   const int *conn=_nodal_connec->begin();
5893   const int *connI=_nodal_connec_index->begin();
5894   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
5895   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
5896   tmpa->alloc(nbOfCells,1);
5897   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
5898   tmpb->fillWithZero();
5899   int *tmp=tmpa->getPointer();
5900   int *tmp2=tmpb->getPointer();
5901   for(const int *i=connI;i!=connI+nbOfCells;i++)
5902     {
5903       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
5904       if(where!=orderEnd)
5905         {
5906           int pos=(int)std::distance(orderBg,where);
5907           tmp2[pos]++;
5908           tmp[std::distance(connI,i)]=pos;
5909         }
5910       else
5911         {
5912           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
5913           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
5914           oss << " has a type " << cm.getRepr() << " not in input array of type !";
5915           throw INTERP_KERNEL::Exception(oss.str());
5916         }
5917     }
5918   nbPerType=tmpb.retn();
5919   return tmpa.retn();
5920 }
5921
5922 /*!
5923  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
5924  *
5925  * \return a new object containing the old to new correspondance.
5926  *
5927  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5928  */
5929 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
5930 {
5931   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5932 }
5933
5934 /*!
5935  * 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.
5936  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
5937  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
5938  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
5939  */
5940 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5941 {
5942   DataArrayInt *nbPerType=0;
5943   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
5944   nbPerType->decrRef();
5945   return tmpa->buildPermArrPerLevel();
5946 }
5947
5948 /*!
5949  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
5950  * The number of cells remains unchanged after the call of this method.
5951  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
5952  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5953  *
5954  * \return the array giving the correspondance old to new.
5955  */
5956 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
5957 {
5958   checkFullyDefined();
5959   computeTypes();
5960   const int *conn=_nodal_connec->begin();
5961   const int *connI=_nodal_connec_index->begin();
5962   int nbOfCells=getNumberOfCells();
5963   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5964   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
5965     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
5966       {
5967         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5968         types.push_back(curType);
5969         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
5970       }
5971   DataArrayInt *ret=DataArrayInt::New();
5972   ret->alloc(nbOfCells,1);
5973   int *retPtr=ret->getPointer();
5974   std::fill(retPtr,retPtr+nbOfCells,-1);
5975   int newCellId=0;
5976   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5977     {
5978       for(const int *i=connI;i!=connI+nbOfCells;i++)
5979         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5980           retPtr[std::distance(connI,i)]=newCellId++;
5981     }
5982   renumberCells(retPtr,false);
5983   return ret;
5984 }
5985
5986 /*!
5987  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
5988  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
5989  * This method makes asumption that connectivity is correctly set before calling.
5990  */
5991 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
5992 {
5993   checkConnectivityFullyDefined();
5994   const int *conn=_nodal_connec->begin();
5995   const int *connI=_nodal_connec_index->begin();
5996   int nbOfCells=getNumberOfCells();
5997   std::vector<MEDCouplingUMesh *> ret;
5998   for(const int *i=connI;i!=connI+nbOfCells;)
5999     {
6000       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6001       int beginCellId=(int)std::distance(connI,i);
6002       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
6003       int endCellId=(int)std::distance(connI,i);
6004       int sz=endCellId-beginCellId;
6005       int *cells=new int[sz];
6006       for(int j=0;j<sz;j++)
6007         cells[j]=beginCellId+j;
6008       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6009       delete [] cells;
6010       ret.push_back(m);
6011     }
6012   return ret;
6013 }
6014
6015 /*!
6016  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6017  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6018  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6019  *
6020  * \return a newly allocated instance, that the caller must manage.
6021  * \throw If \a this contains more than one geometric type.
6022  * \throw If the nodal connectivity of \a this is not fully defined.
6023  * \throw If the internal data is not coherent.
6024  */
6025 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6026 {
6027   checkConnectivityFullyDefined();
6028   if(_types.size()!=1)
6029     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6030   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6031   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6032   ret->setCoords(getCoords());
6033   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6034   if(retC)
6035     {
6036       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6037       retC->setNodalConnectivity(c);
6038     }
6039   else
6040     {
6041       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6042       if(!retD)
6043         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6044       DataArrayInt *c=0,*ci=0;
6045       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6046       MCAuto<DataArrayInt> cs(c),cis(ci);
6047       retD->setNodalConnectivity(cs,cis);
6048     }
6049   return ret.retn();
6050 }
6051
6052 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6053 {
6054   checkConnectivityFullyDefined();
6055   if(_types.size()!=1)
6056     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6057   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6058   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6059   if(cm.isDynamic())
6060     {
6061       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6062       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6063       throw INTERP_KERNEL::Exception(oss.str());
6064     }
6065   int nbCells=getNumberOfCells();
6066   int typi=(int)typ;
6067   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6068   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6069   int *outPtr=connOut->getPointer();
6070   const int *conn=_nodal_connec->begin();
6071   const int *connI=_nodal_connec_index->begin();
6072   nbNodesPerCell++;
6073   for(int i=0;i<nbCells;i++,connI++)
6074     {
6075       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6076         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6077       else
6078         {
6079           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 << ") !";
6080           throw INTERP_KERNEL::Exception(oss.str());
6081         }
6082     }
6083   return connOut.retn();
6084 }
6085
6086 /*!
6087  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
6088  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
6089  * \param nodalConn
6090  * \param nodalConnI
6091  */
6092 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
6093 {
6094   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
6095   checkConnectivityFullyDefined();
6096   if(_types.size()!=1)
6097     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6098   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6099   if(lgth<nbCells)
6100     throw INTERP_KERNEL::Exception(msg0);
6101   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6102   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6103   int *cp(c->getPointer()),*cip(ci->getPointer());
6104   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6105   cip[0]=0;
6106   for(int i=0;i<nbCells;i++,cip++,incip++)
6107     {
6108       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6109       int delta(stop-strt);
6110       if(delta>=1)
6111         {
6112           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6113             cp=std::copy(incp+strt,incp+stop,cp);
6114           else
6115             throw INTERP_KERNEL::Exception(msg0);
6116         }
6117       else
6118         throw INTERP_KERNEL::Exception(msg0);
6119       cip[1]=cip[0]+delta;
6120     }
6121   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6122 }
6123
6124 /*!
6125  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6126  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6127  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6128  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6129  * are not used here to avoid the build of big permutation array.
6130  *
6131  * \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
6132  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6133  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6134  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6135  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6136  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6137  * \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
6138  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6139  */
6140 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6141                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6142                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
6143 {
6144   std::vector<const MEDCouplingUMesh *> ms2;
6145   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6146     if(*it)
6147       {
6148         (*it)->checkConnectivityFullyDefined();
6149         ms2.push_back(*it);
6150       }
6151   if(ms2.empty())
6152     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6153   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6154   int meshDim=ms2[0]->getMeshDimension();
6155   std::vector<const MEDCouplingUMesh *> m1ssm;
6156   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
6157   //
6158   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6159   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
6160   int fake=0,rk=0;
6161   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6162   ret1->alloc(0,1); ret2->alloc(0,1);
6163   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6164     {
6165       if(meshDim!=(*it)->getMeshDimension())
6166         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6167       if(refCoo!=(*it)->getCoords())
6168         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6169       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6170       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6171       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
6172       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6173         {
6174           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6175           m1ssmSingleAuto.push_back(singleCell);
6176           m1ssmSingle.push_back(singleCell);
6177           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6178         }
6179     }
6180   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6181   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6182   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6183   for(std::size_t i=0;i<m1ssm.size();i++)
6184     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6185   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6186   szOfCellGrpOfSameType=ret1->renumber(renum->begin());
6187   idInMsOfCellGrpOfSameType=ret2->renumber(renum->begin());
6188   return ret0.retn();
6189 }
6190
6191 /*!
6192  * This method returns a newly created DataArrayInt instance.
6193  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6194  */
6195 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
6196 {
6197   checkFullyDefined();
6198   const int *conn=_nodal_connec->begin();
6199   const int *connIndex=_nodal_connec_index->begin();
6200   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6201   for(const int *w=begin;w!=end;w++)
6202     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6203       ret->pushBackSilent(*w);
6204   return ret.retn();
6205 }
6206
6207 /*!
6208  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6209  * are in [0:getNumberOfCells())
6210  */
6211 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
6212 {
6213   checkFullyDefined();
6214   const int *conn=_nodal_connec->begin();
6215   const int *connI=_nodal_connec_index->begin();
6216   int nbOfCells=getNumberOfCells();
6217   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
6218   int *tmp=new int[nbOfCells];
6219   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6220     {
6221       int j=0;
6222       for(const int *i=connI;i!=connI+nbOfCells;i++)
6223         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6224           tmp[std::distance(connI,i)]=j++;
6225     }
6226   DataArrayInt *ret=DataArrayInt::New();
6227   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6228   ret->copyStringInfoFrom(*da);
6229   int *retPtr=ret->getPointer();
6230   const int *daPtr=da->begin();
6231   int nbOfElems=da->getNbOfElems();
6232   for(int k=0;k<nbOfElems;k++)
6233     retPtr[k]=tmp[daPtr[k]];
6234   delete [] tmp;
6235   return ret;
6236 }
6237
6238 /*!
6239  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6240  * This method \b works \b for mesh sorted by type.
6241  * cells whose ids is in 'idsPerGeoType' array.
6242  * This method conserves coords and name of mesh.
6243  */
6244 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6245 {
6246   std::vector<int> code=getDistributionOfTypes();
6247   std::size_t nOfTypesInThis=code.size()/3;
6248   int sz=0,szOfType=0;
6249   for(std::size_t i=0;i<nOfTypesInThis;i++)
6250     {
6251       if(code[3*i]!=type)
6252         sz+=code[3*i+1];
6253       else
6254         szOfType=code[3*i+1];
6255     }
6256   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6257     if(*work<0 || *work>=szOfType)
6258       {
6259         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6260         oss << ". It should be in [0," << szOfType << ") !";
6261         throw INTERP_KERNEL::Exception(oss.str());
6262       }
6263   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6264   int *idsPtr=idsTokeep->getPointer();
6265   int offset=0;
6266   for(std::size_t i=0;i<nOfTypesInThis;i++)
6267     {
6268       if(code[3*i]!=type)
6269         for(int j=0;j<code[3*i+1];j++)
6270           *idsPtr++=offset+j;
6271       else
6272         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6273       offset+=code[3*i+1];
6274     }
6275   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6276   ret->copyTinyInfoFrom(this);
6277   return ret.retn();
6278 }
6279
6280 /*!
6281  * This method returns a vector of size 'this->getNumberOfCells()'.
6282  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6283  */
6284 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
6285 {
6286   int ncell=getNumberOfCells();
6287   std::vector<bool> ret(ncell);
6288   const int *cI=getNodalConnectivityIndex()->begin();
6289   const int *c=getNodalConnectivity()->begin();
6290   for(int i=0;i<ncell;i++)
6291     {
6292       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6293       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6294       ret[i]=cm.isQuadratic();
6295     }
6296   return ret;
6297 }
6298
6299 /*!
6300  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6301  */
6302 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6303 {
6304   if(other->getType()!=UNSTRUCTURED)
6305     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6306   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6307   return MergeUMeshes(this,otherC);
6308 }
6309
6310 /*!
6311  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6312  * computed by averaging coordinates of cell nodes, so this method is not a right
6313  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6314  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6315  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6316  *          components. The caller is to delete this array using decrRef() as it is
6317  *          no more needed.
6318  *  \throw If the coordinates array is not set.
6319  *  \throw If the nodal connectivity of cells is not defined.
6320  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6321  */
6322 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
6323 {
6324   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6325   int spaceDim=getSpaceDimension();
6326   int nbOfCells=getNumberOfCells();
6327   ret->alloc(nbOfCells,spaceDim);
6328   ret->copyStringInfoFrom(*getCoords());
6329   double *ptToFill=ret->getPointer();
6330   const int *nodal=_nodal_connec->begin();
6331   const int *nodalI=_nodal_connec_index->begin();
6332   const double *coor=_coords->begin();
6333   for(int i=0;i<nbOfCells;i++)
6334     {
6335       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6336       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6337       ptToFill+=spaceDim;
6338     }
6339   return ret.retn();
6340 }
6341
6342 /*!
6343  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6344  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
6345  * 
6346  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6347  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6348  * 
6349  * \sa MEDCouplingUMesh::computeCellCenterOfMass
6350  * \throw If \a this is not fully defined (coordinates and connectivity)
6351  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6352  */
6353 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
6354 {
6355   checkFullyDefined();
6356   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6357   int spaceDim=getSpaceDimension();
6358   int nbOfCells=getNumberOfCells();
6359   int nbOfNodes=getNumberOfNodes();
6360   ret->alloc(nbOfCells,spaceDim);
6361   double *ptToFill=ret->getPointer();
6362   const int *nodal=_nodal_connec->begin();
6363   const int *nodalI=_nodal_connec_index->begin();
6364   const double *coor=_coords->begin();
6365   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6366     {
6367       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6368       std::fill(ptToFill,ptToFill+spaceDim,0.);
6369       if(type!=INTERP_KERNEL::NORM_POLYHED)
6370         {
6371           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6372             {
6373               if(*conn>=0 && *conn<nbOfNodes)
6374                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6375               else
6376                 {
6377                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
6378                   throw INTERP_KERNEL::Exception(oss.str());
6379                 }
6380             }
6381           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
6382           if(nbOfNodesInCell>0)
6383             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6384           else
6385             {
6386               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
6387               throw INTERP_KERNEL::Exception(oss.str());
6388             }
6389         }
6390       else
6391         {
6392           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
6393           s.erase(-1);
6394           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
6395             {
6396               if(*it>=0 && *it<nbOfNodes)
6397                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
6398               else
6399                 {
6400                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
6401                   throw INTERP_KERNEL::Exception(oss.str());
6402                 }
6403             }
6404           if(!s.empty())
6405             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
6406           else
6407             {
6408               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
6409               throw INTERP_KERNEL::Exception(oss.str());
6410             }
6411         }
6412     }
6413   return ret.retn();
6414 }
6415
6416 /*!
6417  * Returns a new DataArrayDouble holding barycenters of specified cells. The
6418  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
6419  * are specified via an array of cell ids. 
6420  *  \warning Validity of the specified cell ids is not checked! 
6421  *           Valid range is [ 0, \a this->getNumberOfCells() ).
6422  *  \param [in] begin - an array of cell ids of interest.
6423  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
6424  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
6425  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
6426  *          caller is to delete this array using decrRef() as it is no more needed. 
6427  *  \throw If the coordinates array is not set.
6428  *  \throw If the nodal connectivity of cells is not defined.
6429  *
6430  *  \if ENABLE_EXAMPLES
6431  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
6432  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
6433  *  \endif
6434  */
6435 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6436 {
6437   DataArrayDouble *ret=DataArrayDouble::New();
6438   int spaceDim=getSpaceDimension();
6439   int nbOfTuple=(int)std::distance(begin,end);
6440   ret->alloc(nbOfTuple,spaceDim);
6441   double *ptToFill=ret->getPointer();
6442   double *tmp=new double[spaceDim];
6443   const int *nodal=_nodal_connec->begin();
6444   const int *nodalI=_nodal_connec_index->begin();
6445   const double *coor=_coords->begin();
6446   for(const int *w=begin;w!=end;w++)
6447     {
6448       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6449       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6450       ptToFill+=spaceDim;
6451     }
6452   delete [] tmp;
6453   return ret;
6454 }
6455
6456 /*!
6457  * 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".
6458  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
6459  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
6460  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
6461  * This method is useful to detect 2D cells in 3D space that are not coplanar.
6462  * 
6463  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
6464  * \throw If spaceDim!=3 or meshDim!=2.
6465  * \throw If connectivity of \a this is invalid.
6466  * \throw If connectivity of a cell in \a this points to an invalid node.
6467  */
6468 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
6469 {
6470   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
6471   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6472   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
6473     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
6474   ret->alloc(nbOfCells,4);
6475   double *retPtr(ret->getPointer());
6476   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
6477   const double *coor(_coords->begin());
6478   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
6479     {
6480       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
6481       if(nodalI[1]-nodalI[0]>=4)
6482         {
6483           double aa[3]={coor[nodal[nodalI[0]+1+1]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6484                         coor[nodal[nodalI[0]+1+1]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6485                         coor[nodal[nodalI[0]+1+1]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]}
6486           ,bb[3]={coor[nodal[nodalI[0]+1+2]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6487                         coor[nodal[nodalI[0]+1+2]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6488                         coor[nodal[nodalI[0]+1+2]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]};
6489           double cc[3]={aa[1]*bb[2]-aa[2]*bb[1],aa[2]*bb[0]-aa[0]*bb[2],aa[0]*bb[1]-aa[1]*bb[0]};
6490           for(int j=0;j<3;j++)
6491             {
6492               int nodeId(nodal[nodalI[0]+1+j]);
6493               if(nodeId>=0 && nodeId<nbOfNodes)
6494                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
6495               else
6496                 {
6497                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
6498                   throw INTERP_KERNEL::Exception(oss.str());
6499                 }
6500             }
6501           if(sqrt(cc[0]*cc[0]+cc[1]*cc[1]+cc[2]*cc[2])>1e-7)
6502             {
6503               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6504               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6505             }
6506           else
6507             {
6508               if(nodalI[1]-nodalI[0]==4)
6509                 {
6510                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : cell" << i << " : Presence of The 3 colinear points !";
6511                   throw INTERP_KERNEL::Exception(oss.str());
6512                 }
6513               //
6514               double dd[3]={0.,0.,0.};
6515               for(int offset=nodalI[0]+1;offset<nodalI[1];offset++)
6516                 std::transform(coor+3*nodal[offset],coor+3*(nodal[offset]+1),dd,dd,std::plus<double>());
6517               int nbOfNodesInCell(nodalI[1]-nodalI[0]-1);
6518               std::transform(dd,dd+3,dd,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6519               std::copy(dd,dd+3,matrix+4*2);
6520               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6521               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6522             }
6523         }
6524       else
6525         {
6526           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
6527           throw INTERP_KERNEL::Exception(oss.str());
6528         }
6529     }
6530   return ret.retn();
6531 }
6532
6533 /*!
6534  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6535  * 
6536  */
6537 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
6538 {
6539   if(!da)
6540     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6541   da->checkAllocated();
6542   std::string name(da->getName());
6543   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(name,0));
6544   if(name.empty())
6545     ret->setName("Mesh");
6546   ret->setCoords(da);
6547   int nbOfTuples(da->getNumberOfTuples());
6548   MCAuto<DataArrayInt> c(DataArrayInt::New()),cI(DataArrayInt::New());
6549   c->alloc(2*nbOfTuples,1);
6550   cI->alloc(nbOfTuples+1,1);
6551   int *cp(c->getPointer()),*cip(cI->getPointer());
6552   *cip++=0;
6553   for(int i=0;i<nbOfTuples;i++)
6554     {
6555       *cp++=INTERP_KERNEL::NORM_POINT1;
6556       *cp++=i;
6557       *cip++=2*(i+1);
6558     }
6559   ret->setConnectivity(c,cI,true);
6560   return ret.retn();
6561 }
6562
6563 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::Build1DMeshFromCoords(DataArrayDouble *da)
6564 {
6565   if(!da)
6566     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build01MeshFromCoords : instance of DataArrayDouble must be not null !");
6567   da->checkAllocated();
6568   std::string name(da->getName());
6569   MCAuto<MEDCouplingUMesh> ret;
6570   {
6571     MCAuto<MEDCouplingCMesh> tmp(MEDCouplingCMesh::New());
6572     MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6573     arr->alloc(da->getNumberOfTuples());
6574     tmp->setCoordsAt(0,arr);
6575     ret=tmp->buildUnstructured();
6576   }
6577   ret->setCoords(da);
6578   if(name.empty())
6579     ret->setName("Mesh");
6580   else
6581     ret->setName(name);
6582   return ret;
6583 }
6584
6585 /*!
6586  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
6587  * Cells and nodes of
6588  * the first mesh precede cells and nodes of the second mesh within the result mesh.
6589  *  \param [in] mesh1 - the first mesh.
6590  *  \param [in] mesh2 - the second mesh.
6591  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6592  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6593  *          is no more needed.
6594  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6595  *  \throw If the coordinates array is not set in none of the meshes.
6596  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6597  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6598  */
6599 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6600 {
6601   std::vector<const MEDCouplingUMesh *> tmp(2);
6602   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6603   return MergeUMeshes(tmp);
6604 }
6605
6606 /*!
6607  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
6608  * Cells and nodes of
6609  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
6610  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
6611  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6612  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6613  *          is no more needed.
6614  *  \throw If \a a.size() == 0.
6615  *  \throw If \a a[ *i* ] == NULL.
6616  *  \throw If the coordinates array is not set in none of the meshes.
6617  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6618  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6619  */
6620 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const std::vector<const MEDCouplingUMesh *>& a)
6621 {
6622   std::size_t sz=a.size();
6623   if(sz==0)
6624     return MergeUMeshesLL(a);
6625   for(std::size_t ii=0;ii<sz;ii++)
6626     if(!a[ii])
6627       {
6628         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6629         throw INTERP_KERNEL::Exception(oss.str());
6630       }
6631   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
6632   std::vector< const MEDCouplingUMesh * > aa(sz);
6633   int spaceDim=-3;
6634   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6635     {
6636       const MEDCouplingUMesh *cur=a[i];
6637       const DataArrayDouble *coo=cur->getCoords();
6638       if(coo)
6639         spaceDim=coo->getNumberOfComponents();
6640     }
6641   if(spaceDim==-3)
6642     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6643   for(std::size_t i=0;i<sz;i++)
6644     {
6645       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6646       aa[i]=bb[i];
6647     }
6648   return MergeUMeshesLL(aa);
6649 }
6650
6651 /*!
6652  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
6653  * dimension and sharing the node coordinates array.
6654  * All cells of the first mesh precede all cells of the second mesh
6655  * within the result mesh.
6656  *  \param [in] mesh1 - the first mesh.
6657  *  \param [in] mesh2 - the second mesh.
6658  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6659  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6660  *          is no more needed.
6661  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6662  *  \throw If the meshes do not share the node coordinates array.
6663  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6664  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6665  */
6666 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6667 {
6668   std::vector<const MEDCouplingUMesh *> tmp(2);
6669   tmp[0]=mesh1; tmp[1]=mesh2;
6670   return MergeUMeshesOnSameCoords(tmp);
6671 }
6672
6673 /*!
6674  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6675  * dimension and sharing the node coordinates array.
6676  * All cells of the *i*-th mesh precede all cells of the
6677  * (*i*+1)-th mesh within the result mesh.
6678  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6679  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6680  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6681  *          is no more needed.
6682  *  \throw If \a a.size() == 0.
6683  *  \throw If \a a[ *i* ] == NULL.
6684  *  \throw If the meshes do not share the node coordinates array.
6685  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6686  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6687  */
6688 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6689 {
6690   if(meshes.empty())
6691     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6692   for(std::size_t ii=0;ii<meshes.size();ii++)
6693     if(!meshes[ii])
6694       {
6695         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6696         throw INTERP_KERNEL::Exception(oss.str());
6697       }
6698   const DataArrayDouble *coords=meshes.front()->getCoords();
6699   int meshDim=meshes.front()->getMeshDimension();
6700   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6701   int meshLgth=0;
6702   int meshIndexLgth=0;
6703   for(;iter!=meshes.end();iter++)
6704     {
6705       if(coords!=(*iter)->getCoords())
6706         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6707       if(meshDim!=(*iter)->getMeshDimension())
6708         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6709       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
6710       meshIndexLgth+=(*iter)->getNumberOfCells();
6711     }
6712   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
6713   nodal->alloc(meshLgth,1);
6714   int *nodalPtr=nodal->getPointer();
6715   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
6716   nodalIndex->alloc(meshIndexLgth+1,1);
6717   int *nodalIndexPtr=nodalIndex->getPointer();
6718   int offset=0;
6719   for(iter=meshes.begin();iter!=meshes.end();iter++)
6720     {
6721       const int *nod=(*iter)->getNodalConnectivity()->begin();
6722       const int *index=(*iter)->getNodalConnectivityIndex()->begin();
6723       int nbOfCells=(*iter)->getNumberOfCells();
6724       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
6725       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6726       if(iter!=meshes.begin())
6727         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6728       else
6729         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6730       offset+=meshLgth2;
6731     }
6732   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6733   ret->setName("merge");
6734   ret->setMeshDimension(meshDim);
6735   ret->setConnectivity(nodal,nodalIndex,true);
6736   ret->setCoords(coords);
6737   return ret;
6738 }
6739
6740 /*!
6741  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6742  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
6743  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
6744  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
6745  * New" mode are returned for each input mesh.
6746  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6747  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
6748  *          valid values [0,1,2], see zipConnectivityTraducer().
6749  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
6750  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
6751  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
6752  *          no more needed.
6753  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6754  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6755  *          is no more needed.
6756  *  \throw If \a meshes.size() == 0.
6757  *  \throw If \a meshes[ *i* ] == NULL.
6758  *  \throw If the meshes do not share the node coordinates array.
6759  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
6760  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
6761  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
6762  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
6763  */
6764 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6765 {
6766   //All checks are delegated to MergeUMeshesOnSameCoords
6767   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6768   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6769   corr.resize(meshes.size());
6770   std::size_t nbOfMeshes=meshes.size();
6771   int offset=0;
6772   const int *o2nPtr=o2n->begin();
6773   for(std::size_t i=0;i<nbOfMeshes;i++)
6774     {
6775       DataArrayInt *tmp=DataArrayInt::New();
6776       int curNbOfCells=meshes[i]->getNumberOfCells();
6777       tmp->alloc(curNbOfCells,1);
6778       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6779       offset+=curNbOfCells;
6780       tmp->setName(meshes[i]->getName());
6781       corr[i]=tmp;
6782     }
6783   return ret.retn();
6784 }
6785
6786 /*!
6787  * Makes all given meshes share the nodal connectivity array. The common connectivity
6788  * array is created by concatenating the connectivity arrays of all given meshes. All
6789  * the given meshes must be of the same space dimension but dimension of cells **can
6790  * differ**. This method is particulary useful in MEDLoader context to build a \ref
6791  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6792  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
6793  *  \param [in,out] meshes - a vector of meshes to update.
6794  *  \throw If any of \a meshes is NULL.
6795  *  \throw If the coordinates array is not set in any of \a meshes.
6796  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6797  *  \throw If \a meshes are of different space dimension.
6798  */
6799 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
6800 {
6801   std::size_t sz=meshes.size();
6802   if(sz==0 || sz==1)
6803     return;
6804   std::vector< const DataArrayDouble * > coords(meshes.size());
6805   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6806   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6807     {
6808       if((*it))
6809         {
6810           (*it)->checkConnectivityFullyDefined();
6811           const DataArrayDouble *coo=(*it)->getCoords();
6812           if(coo)
6813             *it2=coo;
6814           else
6815             {
6816               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6817               oss << " has no coordinate array defined !";
6818               throw INTERP_KERNEL::Exception(oss.str());
6819             }
6820         }
6821       else
6822         {
6823           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6824           oss << " is null !";
6825           throw INTERP_KERNEL::Exception(oss.str());
6826         }
6827     }
6828   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6829   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6830   int offset=(*it)->getNumberOfNodes();
6831   (*it++)->setCoords(res);
6832   for(;it!=meshes.end();it++)
6833     {
6834       int oldNumberOfNodes=(*it)->getNumberOfNodes();
6835       (*it)->setCoords(res);
6836       (*it)->shiftNodeNumbersInConn(offset);
6837       offset+=oldNumberOfNodes;
6838     }
6839 }
6840
6841 /*!
6842  * Merges nodes coincident with a given precision within all given meshes that share
6843  * the nodal connectivity array. The given meshes **can be of different** mesh
6844  * dimension. This method is particulary useful in MEDLoader context to build a \ref
6845  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6846  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
6847  *  \param [in,out] meshes - a vector of meshes to update.
6848  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
6849  *  \throw If any of \a meshes is NULL.
6850  *  \throw If the \a meshes do not share the same node coordinates array.
6851  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6852  */
6853 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
6854 {
6855   if(meshes.empty())
6856     return ;
6857   std::set<const DataArrayDouble *> s;
6858   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6859     {
6860       if(*it)
6861         s.insert((*it)->getCoords());
6862       else
6863         {
6864           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 !";
6865           throw INTERP_KERNEL::Exception(oss.str());
6866         }
6867     }
6868   if(s.size()!=1)
6869     {
6870       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 !";
6871       throw INTERP_KERNEL::Exception(oss.str());
6872     }
6873   const DataArrayDouble *coo=*(s.begin());
6874   if(!coo)
6875     return;
6876   //
6877   DataArrayInt *comm,*commI;
6878   coo->findCommonTuples(eps,-1,comm,commI);
6879   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
6880   int oldNbOfNodes=coo->getNumberOfTuples();
6881   int newNbOfNodes;
6882   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6883   if(oldNbOfNodes==newNbOfNodes)
6884     return ;
6885   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->begin(),newNbOfNodes);
6886   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6887     {
6888       (*it)->renumberNodesInConn(o2n->begin());
6889       (*it)->setCoords(newCoords);
6890     } 
6891 }
6892
6893
6894 /*!
6895  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
6896  */
6897 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6898 {
6899   std::size_t i, ip1;
6900   double v[3]={0.,0.,0.};
6901   std::size_t sz=std::distance(begin,end);
6902   if(isQuadratic)
6903     sz/=2;
6904   for(i=0;i<sz;i++)
6905     {
6906       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];
6907       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6908       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6909     }
6910   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6911
6912   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
6913   // SEG3 forming a circle):
6914   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
6915     {
6916       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
6917       for(std::size_t j=0;j<sz;j++)
6918         {
6919           if (j%2)  // current point i is quadratic, next point i+1 is standard
6920             {
6921               i = sz+j;
6922               ip1 = (j+1)%sz; // ip1 = "i+1"
6923             }
6924           else      // current point i is standard, next point i+1 is quadratic
6925             {
6926               i = j;
6927               ip1 = j+sz;
6928             }
6929           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
6930           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
6931           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
6932         }
6933       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6934     }
6935   return (ret>0.);
6936 }
6937
6938 /*!
6939  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
6940  */
6941 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6942 {
6943   std::vector<std::pair<int,int> > edges;
6944   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6945   const int *bgFace=begin;
6946   for(std::size_t i=0;i<nbOfFaces;i++)
6947     {
6948       const int *endFace=std::find(bgFace+1,end,-1);
6949       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6950       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6951         {
6952           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6953           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6954             return false;
6955           edges.push_back(p1);
6956         }
6957       bgFace=endFace+1;
6958     }
6959   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6960 }
6961
6962 /*!
6963  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
6964  */
6965 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
6966 {
6967   double vec0[3],vec1[3];
6968   std::size_t sz=std::distance(begin,end);
6969   if(sz%2!=0)
6970     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
6971   int nbOfNodes=(int)sz/2;
6972   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
6973   const double *pt0=coords+3*begin[0];
6974   const double *pt1=coords+3*begin[nbOfNodes];
6975   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
6976   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
6977 }
6978
6979 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
6980 {
6981   std::size_t sz=std::distance(begin,end);
6982   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
6983   std::size_t nbOfNodes(sz/2);
6984   std::copy(begin,end,(int *)tmp);
6985   for(std::size_t j=1;j<nbOfNodes;j++)
6986     {
6987       begin[j]=tmp[nbOfNodes-j];
6988       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
6989     }
6990 }
6991
6992 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
6993 {
6994   std::size_t sz=std::distance(begin,end);
6995   if(sz!=4)
6996     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
6997   double vec0[3],vec1[3];
6998   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
6999   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]; 
7000   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;
7001 }
7002
7003 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7004 {
7005   std::size_t sz=std::distance(begin,end);
7006   if(sz!=5)
7007     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
7008   double vec0[3];
7009   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7010   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7011   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7012 }
7013
7014 /*!
7015  * 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 ) 
7016  * 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
7017  * a 2D space.
7018  *
7019  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7020  * \param [in] coords the coordinates with nb of components exactly equal to 3
7021  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7022  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7023  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7024  */
7025 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, int index, DataArrayInt *res, MEDCouplingUMesh *faces,
7026                                               DataArrayInt *E_Fi, DataArrayInt *E_F, DataArrayInt *F_Ei, DataArrayInt *F_E)
7027 {
7028   int nbFaces = E_Fi->getIJ(index + 1, 0) - E_Fi->getIJ(index, 0);
7029   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7030   double *vPtr=v->getPointer();
7031   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,2);
7032   double *pPtr=p->getPointer();
7033   int *e_fi = E_Fi->getPointer(), *e_f = E_F->getPointer(), *f_ei = F_Ei->getPointer(), *f_e = F_E->getPointer();
7034   const int *f_idx = faces->getNodalConnectivityIndex()->getPointer(), *f_cnn = faces->getNodalConnectivity()->getPointer();
7035   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7036     {
7037       int face = e_f[e_fi[index] + i];
7038       ComputeVecAndPtOfFace(eps, coords->begin(), f_cnn + f_idx[face] + 1, f_cnn + f_idx[face + 1], vPtr, pPtr);
7039       // to differentiate faces going to different cells:
7040       pPtr++, *pPtr = 0;
7041       for (int j = f_ei[face]; j < f_ei[face + 1]; j++)
7042         *pPtr += f_e[j];
7043     }
7044   pPtr=p->getPointer(); vPtr=v->getPointer();
7045   DataArrayInt *comm1=0,*commI1=0;
7046   v->findCommonTuples(eps,-1,comm1,commI1);
7047   for (int i = 0; i < nbFaces; i++)
7048     if (comm1->findIdFirstEqual(i) < 0)
7049       {
7050         comm1->pushBackSilent(i);
7051         commI1->pushBackSilent(comm1->getNumberOfTuples());
7052       }
7053   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7054   const int *comm1Ptr=comm1->begin();
7055   const int *commI1Ptr=commI1->begin();
7056   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7057   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7058   //
7059   for(int i=0;i<nbOfGrps1;i++)
7060     {
7061       int vecId=comm1Ptr[commI1Ptr[i]];
7062       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7063       DataArrayInt *comm2=0,*commI2=0;
7064       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7065       for (int j = 0; j < commI1Ptr[i+1] - commI1Ptr[i]; j++)
7066         if (comm2->findIdFirstEqual(j) < 0)
7067           {
7068             comm2->pushBackSilent(j);
7069             commI2->pushBackSilent(comm2->getNumberOfTuples());
7070           }
7071       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7072       const int *comm2Ptr=comm2->begin();
7073       const int *commI2Ptr=commI2->begin();
7074       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7075       for(int j=0;j<nbOfGrps2;j++)
7076         {
7077           if(commI2Ptr[j+1] == commI2Ptr[j] + 1)
7078             {
7079               int face = e_f[e_fi[index] + comm1Ptr[commI1Ptr[i] + comm2Ptr[commI2Ptr[j]]]]; //hmmm
7080               res->insertAtTheEnd(f_cnn + f_idx[face] + 1, f_cnn + f_idx[face + 1]);
7081               res->pushBackSilent(-1);
7082             }
7083           else
7084             {
7085               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7086               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
7087               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7088               ids2->transformWithIndArr(e_f + e_fi[index], e_f + e_fi[index + 1]);
7089               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(faces->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7090               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7091               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7092               const int *idsNodePtr=idsNode->begin();
7093               double center[3]; center[0]=pPtr[2*pointId]*vPtr[3*vecId]; center[1]=pPtr[2*pointId]*vPtr[3*vecId+1]; center[2]=pPtr[2*pointId]*vPtr[3*vecId+2];
7094               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7095               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7096               if(std::abs(norm)>eps)
7097                 {
7098                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7099                   mm3->rotate(center,vec,angle);
7100                 }
7101               mm3->changeSpaceDimension(2);
7102               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7103               const int *conn4=mm4->getNodalConnectivity()->begin();
7104               const int *connI4=mm4->getNodalConnectivityIndex()->begin();
7105               int nbOfCells=mm4->getNumberOfCells();
7106               for(int k=0;k<nbOfCells;k++)
7107                 {
7108                   int l=0;
7109                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7110                     res->pushBackSilent(idsNodePtr[*work]);
7111                   res->pushBackSilent(-1);
7112                 }
7113             }
7114         }
7115     }
7116   res->popBackSilent();
7117 }
7118
7119 /*!
7120  * 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
7121  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7122  * 
7123  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7124  * \param [in] coords coordinates expected to have 3 components.
7125  * \param [in] begin start of the nodal connectivity of the face.
7126  * \param [in] end end of the nodal connectivity (excluded) of the face.
7127  * \param [out] v the normalized vector of size 3
7128  * \param [out] p the pos of plane
7129  */
7130 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
7131 {
7132   std::size_t nbPoints=std::distance(begin,end);
7133   if(nbPoints<3)
7134     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7135   double vec[3]={0.,0.,0.};
7136   std::size_t j=0;
7137   bool refFound=false;
7138   for(;j<nbPoints-1 && !refFound;j++)
7139     {
7140       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7141       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7142       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7143       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7144       if(norm>eps)
7145         {
7146           refFound=true;
7147           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7148         }
7149     }
7150   for(std::size_t i=j;i<nbPoints-1;i++)
7151     {
7152       double curVec[3];
7153       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7154       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7155       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7156       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7157       if(norm<eps)
7158         continue;
7159       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7160       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];
7161       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7162       if(norm>eps)
7163         {
7164           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7165           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7166           return ;
7167         }
7168     }
7169   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7170 }
7171
7172 /*!
7173  * This method tries to obtain a well oriented polyhedron.
7174  * If the algorithm fails, an exception will be thrown.
7175  */
7176 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
7177 {
7178   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7179   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7180   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7181   isPerm[0]=true;
7182   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7183   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7184   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7185   //
7186   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7187     {
7188       bgFace=begin;
7189       std::size_t smthChanged=0;
7190       for(std::size_t i=0;i<nbOfFaces;i++)
7191         {
7192           endFace=std::find(bgFace+1,end,-1);
7193           nbOfEdgesInFace=std::distance(bgFace,endFace);
7194           if(!isPerm[i])
7195             {
7196               bool b;
7197               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7198                 {
7199                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7200                   std::pair<int,int> p2(p1.second,p1.first);
7201                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7202                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7203                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7204                 }
7205               if(isPerm[i])
7206                 { 
7207                   if(!b)
7208                     std::reverse(bgFace+1,endFace);
7209                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7210                     {
7211                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7212                       std::pair<int,int> p2(p1.second,p1.first);
7213                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7214                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7215                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7216                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7217                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7218                       if(it!=edgesOK.end())
7219                         {
7220                           edgesOK.erase(it);
7221                           edgesFinished.push_back(p1);
7222                         }
7223                       else
7224                         edgesOK.push_back(p1);
7225                     }
7226                 }
7227             }
7228           bgFace=endFace+1;
7229         }
7230       if(smthChanged==0)
7231         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7232     }
7233   if(!edgesOK.empty())
7234     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7235   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7236     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7237       bgFace=begin;
7238       for(std::size_t i=0;i<nbOfFaces;i++)
7239         {
7240           endFace=std::find(bgFace+1,end,-1);
7241           std::reverse(bgFace+1,endFace);
7242           bgFace=endFace+1;
7243         }
7244     }
7245 }
7246
7247
7248 /*!
7249  * This method makes the assumption spacedimension == meshdimension == 2.
7250  * This method works only for linear cells.
7251  * 
7252  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7253  */
7254 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
7255 {
7256   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7257     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7258   MCAuto<MEDCouplingUMesh> skin(computeSkin());
7259   int oldNbOfNodes(skin->getNumberOfNodes());
7260   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
7261   int nbOfNodesExpected(skin->getNumberOfNodes());
7262   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
7263   int nbCells(skin->getNumberOfCells());
7264   if(nbCells==nbOfNodesExpected)
7265     return buildUnionOf2DMeshLinear(skin,n2o);
7266   else if(2*nbCells==nbOfNodesExpected)
7267     return buildUnionOf2DMeshQuadratic(skin,n2o);
7268   else
7269     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
7270 }
7271
7272 /*!
7273  * This method makes the assumption spacedimension == meshdimension == 3.
7274  * This method works only for linear cells.
7275  * 
7276  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7277  */
7278 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
7279 {
7280   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7281     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7282   MCAuto<MEDCouplingUMesh> m=computeSkin();
7283   const int *conn=m->getNodalConnectivity()->begin();
7284   const int *connI=m->getNodalConnectivityIndex()->begin();
7285   int nbOfCells=m->getNumberOfCells();
7286   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7287   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7288   if(nbOfCells<1)
7289     return ret.retn();
7290   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7291   for(int i=1;i<nbOfCells;i++)
7292     {
7293       *work++=-1;
7294       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7295     }
7296   return ret.retn();
7297 }
7298
7299 /*!
7300  * \brief Creates a graph of cell neighbors
7301  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
7302  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
7303  *  For example
7304  *  - index:  0 3 5 6 6
7305  *  - value:  1 2 3 2 3 3
7306  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7307  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
7308  */
7309 MEDCouplingSkyLineArray* MEDCouplingUMesh::generateGraph() const
7310 {
7311   checkConnectivityFullyDefined();
7312
7313   int meshDim = this->getMeshDimension();
7314   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
7315   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
7316   this->getReverseNodalConnectivity(revConn,indexr);
7317   const int* indexr_ptr=indexr->begin();
7318   const int* revConn_ptr=revConn->begin();
7319
7320   const MEDCoupling::DataArrayInt* index;
7321   const MEDCoupling::DataArrayInt* conn;
7322   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
7323   index=this->getNodalConnectivityIndex();
7324   int nbCells=this->getNumberOfCells();
7325   const int* index_ptr=index->begin();
7326   const int* conn_ptr=conn->begin();
7327
7328   //creating graph arcs (cell to cell relations)
7329   //arcs are stored in terms of (index,value) notation
7330   // 0 3 5 6 6
7331   // 1 2 3 2 3 3
7332   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7333   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
7334
7335   //warning here one node have less than or equal effective number of cell with it
7336   //but cell could have more than effective nodes
7337   //because other equals nodes in other domain (with other global inode)
7338   std::vector <int> cell2cell_index(nbCells+1,0);
7339   std::vector <int> cell2cell;
7340   cell2cell.reserve(3*nbCells);
7341
7342   for (int icell=0; icell<nbCells;icell++)
7343     {
7344       std::map<int,int > counter;
7345       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
7346         {
7347           int inode=conn_ptr[iconn];
7348           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
7349             {
7350               int icell2=revConn_ptr[iconnr];
7351               std::map<int,int>::iterator iter=counter.find(icell2);
7352               if (iter!=counter.end()) (iter->second)++;
7353               else counter.insert(std::make_pair(icell2,1));
7354             }
7355         }
7356       for (std::map<int,int>::const_iterator iter=counter.begin();
7357            iter!=counter.end(); iter++)
7358         if (iter->second >= meshDim)
7359           {
7360             cell2cell_index[icell+1]++;
7361             cell2cell.push_back(iter->first);
7362           }
7363     }
7364   indexr->decrRef();
7365   revConn->decrRef();
7366   cell2cell_index[0]=0;
7367   for (int icell=0; icell<nbCells;icell++)
7368     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
7369
7370   //filling up index and value to create skylinearray structure
7371   MEDCouplingSkyLineArray * array(MEDCouplingSkyLineArray::New(cell2cell_index,cell2cell));
7372   return array;
7373 }
7374
7375
7376 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
7377 {
7378   int nbOfCells=getNumberOfCells();
7379   if(nbOfCells<=0)
7380     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7381   ofs << "  <" << getVTKDataSetType() << ">\n";
7382   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7383   ofs << "      <PointData>\n" << pointData << std::endl;
7384   ofs << "      </PointData>\n";
7385   ofs << "      <CellData>\n" << cellData << std::endl;
7386   ofs << "      </CellData>\n";
7387   ofs << "      <Points>\n";
7388   if(getSpaceDimension()==3)
7389     _coords->writeVTK(ofs,8,"Points",byteData);
7390   else
7391     {
7392       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7393       coo->writeVTK(ofs,8,"Points",byteData);
7394     }
7395   ofs << "      </Points>\n";
7396   ofs << "      <Cells>\n";
7397   const int *cPtr=_nodal_connec->begin();
7398   const int *cIPtr=_nodal_connec_index->begin();
7399   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7400   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7401   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7402   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7403   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7404   int szFaceOffsets=0,szConn=0;
7405   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7406     {
7407       *w2=cPtr[cIPtr[i]];
7408       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7409         {
7410           *w1=-1;
7411           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7412           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7413         }
7414       else
7415         {
7416           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7417           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7418           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7419           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7420           w4=std::copy(c.begin(),c.end(),w4);
7421         }
7422     }
7423   types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
7424   types->writeVTK(ofs,8,"UInt8","types",byteData);
7425   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
7426   if(szFaceOffsets!=0)
7427     {//presence of Polyhedra
7428       connectivity->reAlloc(szConn);
7429       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
7430       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7431       w1=faces->getPointer();
7432       for(int i=0;i<nbOfCells;i++)
7433         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7434           {
7435             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7436             *w1++=nbFaces;
7437             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7438             for(int j=0;j<nbFaces;j++)
7439               {
7440                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7441                 *w1++=(int)std::distance(w6,w5);
7442                 w1=std::copy(w6,w5,w1);
7443                 w6=w5+1;
7444               }
7445           }
7446       faces->writeVTK(ofs,8,"Int32","faces",byteData);
7447     }
7448   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
7449   ofs << "      </Cells>\n";
7450   ofs << "    </Piece>\n";
7451   ofs << "  </" << getVTKDataSetType() << ">\n";
7452 }
7453
7454 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
7455 {
7456   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
7457   if(_mesh_dim==-2)
7458     { stream << " Not set !"; return ; }
7459   stream << " Mesh dimension : " << _mesh_dim << ".";
7460   if(_mesh_dim==-1)
7461     return ;
7462   if(!_coords)
7463     { stream << " No coordinates set !"; return ; }
7464   if(!_coords->isAllocated())
7465     { stream << " Coordinates set but not allocated !"; return ; }
7466   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
7467   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
7468   if(!_nodal_connec_index)
7469     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
7470   if(!_nodal_connec_index->isAllocated())
7471     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
7472   int lgth=_nodal_connec_index->getNumberOfTuples();
7473   int cpt=_nodal_connec_index->getNumberOfComponents();
7474   if(cpt!=1 || lgth<1)
7475     return ;
7476   stream << std::endl << "Number of cells : " << lgth-1 << ".";
7477 }
7478
7479 std::string MEDCouplingUMesh::getVTKDataSetType() const
7480 {
7481   return std::string("UnstructuredGrid");
7482 }
7483
7484 std::string MEDCouplingUMesh::getVTKFileExtension() const
7485 {
7486   return std::string("vtu");
7487 }
7488
7489
7490
7491 /**
7492  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
7493  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
7494  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
7495  * The caller is to deal with the resulting DataArrayInt.
7496  *  \throw If the coordinate array is not set.
7497  *  \throw If the nodal connectivity of the cells is not defined.
7498  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
7499  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
7500  *
7501  * \sa DataArrayInt::sortEachPairToMakeALinkedList
7502  */
7503 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
7504 {
7505   checkFullyDefined();
7506   if(getMeshDimension()!=1)
7507     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
7508
7509   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
7510   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
7511   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
7512   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
7513   const int *d(_d->begin()), *dI(_dI->begin());
7514   const int *rD(_rD->begin()), *rDI(_rDI->begin());
7515   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
7516   const int * dsi(_dsi->begin());
7517   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
7518   m_points=0;
7519   if (dsii->getNumberOfTuples())
7520     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
7521
7522   int nc(getNumberOfCells());
7523   MCAuto<DataArrayInt> result(DataArrayInt::New());
7524   result->alloc(nc,1);
7525
7526   // set of edges not used so far
7527   std::set<int> edgeSet;
7528   for (int i=0; i<nc; edgeSet.insert(i), i++);
7529
7530   int startSeg=0;
7531   int newIdx=0;
7532   // while we have points with only one neighbor segments
7533   do
7534     {
7535       std::list<int> linePiece;
7536       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
7537       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
7538         {
7539           // Fill the list forward (resp. backward) from the start segment:
7540           int activeSeg = startSeg;
7541           int prevPointId = -20;
7542           int ptId;
7543           while (!edgeSet.empty())
7544             {
7545               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
7546                 {
7547                   if (direction==0)
7548                     linePiece.push_back(activeSeg);
7549                   else
7550                     linePiece.push_front(activeSeg);
7551                   edgeSet.erase(activeSeg);
7552                 }
7553
7554               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
7555               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
7556               if (dsi[ptId] == 1) // hitting the end of the line
7557                 break;
7558               prevPointId = ptId;
7559               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
7560               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
7561             }
7562         }
7563       // Done, save final piece into DA:
7564       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
7565       newIdx += linePiece.size();
7566
7567       // identify next valid start segment (one which is not consumed)
7568       if(!edgeSet.empty())
7569         startSeg = *(edgeSet.begin());
7570     }
7571   while (!edgeSet.empty());
7572   return result.retn();
7573 }
7574
7575 /**
7576  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
7577  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
7578  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
7579  * a minimal creation of new nodes is wanted.
7580  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
7581  * nodes if a SEG3 is split without information of middle.
7582  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
7583  * avoid to have a non conform mesh.
7584  *
7585  * \return int - the number of new nodes created (in most of cases 0).
7586  * 
7587  * \throw If \a this is not coherent.
7588  * \throw If \a this has not spaceDim equal to 2.
7589  * \throw If \a this has not meshDim equal to 2.
7590  * \throw If some subcells needed to be split are orphan.
7591  * \sa MEDCouplingUMesh::conformize2D
7592  */
7593 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
7594 {
7595   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
7596     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
7597   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
7598   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
7599     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
7600   if(midOpt==0 && midOptI==0)
7601     {
7602       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
7603       return 0;
7604     }
7605   else if(midOpt!=0 && midOptI!=0)
7606     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
7607   else
7608     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
7609 }
7610
7611 /*!
7612  * 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
7613  * 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
7614  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7615  * 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
7616  * 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.
7617  * 
7618  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7619  */
7620 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
7621 {
7622   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7623   if(sz>=4)
7624     {
7625       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7626       if(cm.getDimension()==2)
7627         {
7628           const int *node=nodalConnBg+1;
7629           int startNode=*node++;
7630           double refX=coords[2*startNode];
7631           for(;node!=nodalConnEnd;node++)
7632             {
7633               if(coords[2*(*node)]<refX)
7634                 {
7635                   startNode=*node;
7636                   refX=coords[2*startNode];
7637                 }
7638             }
7639           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7640           refX=1e300;
7641           double tmp1;
7642           double tmp2[2];
7643           double angle0=-M_PI/2;
7644           //
7645           int nextNode=-1;
7646           int prevNode=-1;
7647           double resRef;
7648           double angleNext=0.;
7649           while(nextNode!=startNode)
7650             {
7651               nextNode=-1;
7652               resRef=1e300;
7653               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7654                 {
7655                   if(*node!=tmpOut.back() && *node!=prevNode)
7656                     {
7657                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7658                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7659                       double res;
7660                       if(angleM<=angle0)
7661                         res=angle0-angleM;
7662                       else
7663                         res=angle0-angleM+2.*M_PI;
7664                       if(res<resRef)
7665                         {
7666                           nextNode=*node;
7667                           resRef=res;
7668                           angleNext=angleM;
7669                         }
7670                     }
7671                 }
7672               if(nextNode!=startNode)
7673                 {
7674                   angle0=angleNext-M_PI;
7675                   if(angle0<-M_PI)
7676                     angle0+=2*M_PI;
7677                   prevNode=tmpOut.back();
7678                   tmpOut.push_back(nextNode);
7679                 }
7680             }
7681           std::vector<int> tmp3(2*(sz-1));
7682           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7683           std::copy(nodalConnBg+1,nodalConnEnd,it);
7684           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7685             {
7686               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7687               return false;
7688             }
7689           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7690             {
7691               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7692               return false;
7693             }
7694           else
7695             {
7696               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7697               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7698               return true;
7699             }
7700         }
7701       else
7702         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7703     }
7704   else
7705     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7706 }
7707
7708 /*!
7709  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7710  * 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.
7711  * 
7712  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7713  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7714  * \param [in,out] arr array in which the remove operation will be done.
7715  * \param [in,out] arrIndx array in the remove operation will modify
7716  * \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])
7717  * \return true if \b arr and \b arrIndx have been modified, false if not.
7718  */
7719 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
7720 {
7721   if(!arrIndx || !arr)
7722     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7723   if(offsetForRemoval<0)
7724     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7725   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7726   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7727   int *arrIPtr=arrIndx->getPointer();
7728   *arrIPtr++=0;
7729   int previousArrI=0;
7730   const int *arrPtr=arr->begin();
7731   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7732   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7733     {
7734       if(*arrIPtr-previousArrI>offsetForRemoval)
7735         {
7736           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7737             {
7738               if(s.find(*work)==s.end())
7739                 arrOut.push_back(*work);
7740             }
7741         }
7742       previousArrI=*arrIPtr;
7743       *arrIPtr=(int)arrOut.size();
7744     }
7745   if(arr->getNumberOfTuples()==arrOut.size())
7746     return false;
7747   arr->alloc((int)arrOut.size(),1);
7748   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7749   return true;
7750 }
7751
7752 /*!
7753  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7754  * (\ref numbering-indirect).
7755  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7756  * The selection of extraction is done standardly in new2old format.
7757  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7758  *
7759  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7760  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7761  * \param [in] arrIn arr origin array from which the extraction will be done.
7762  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7763  * \param [out] arrOut the resulting array
7764  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7765  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
7766  */
7767 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7768                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7769 {
7770   if(!arrIn || !arrIndxIn)
7771     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7772   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7773   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7774     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
7775   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7776   const int *arrInPtr=arrIn->begin();
7777   const int *arrIndxPtr=arrIndxIn->begin();
7778   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7779   if(nbOfGrps<0)
7780     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7781   int maxSizeOfArr=arrIn->getNumberOfTuples();
7782   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7783   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7784   arrIo->alloc((int)(sz+1),1);
7785   const int *idsIt=idsOfSelectBg;
7786   int *work=arrIo->getPointer();
7787   *work++=0;
7788   int lgth=0;
7789   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7790     {
7791       if(*idsIt>=0 && *idsIt<nbOfGrps)
7792         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7793       else
7794         {
7795           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7796           throw INTERP_KERNEL::Exception(oss.str());
7797         }
7798       if(lgth>=work[-1])
7799         *work=lgth;
7800       else
7801         {
7802           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7803           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7804           throw INTERP_KERNEL::Exception(oss.str());
7805         }
7806     }
7807   arro->alloc(lgth,1);
7808   work=arro->getPointer();
7809   idsIt=idsOfSelectBg;
7810   for(std::size_t i=0;i<sz;i++,idsIt++)
7811     {
7812       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7813         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7814       else
7815         {
7816           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7817           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7818           throw INTERP_KERNEL::Exception(oss.str());
7819         }
7820     }
7821   arrOut=arro.retn();
7822   arrIndexOut=arrIo.retn();
7823 }
7824
7825 /*!
7826  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7827  * (\ref numbering-indirect).
7828  * 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 ).
7829  * The selection of extraction is done standardly in new2old format.
7830  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7831  *
7832  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
7833  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
7834  * \param [in] idsOfSelectStep
7835  * \param [in] arrIn arr origin array from which the extraction will be done.
7836  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7837  * \param [out] arrOut the resulting array
7838  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7839  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
7840  */
7841 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7842                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7843 {
7844   if(!arrIn || !arrIndxIn)
7845     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
7846   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7847   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7848     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
7849   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
7850   const int *arrInPtr=arrIn->begin();
7851   const int *arrIndxPtr=arrIndxIn->begin();
7852   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7853   if(nbOfGrps<0)
7854     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7855   int maxSizeOfArr=arrIn->getNumberOfTuples();
7856   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7857   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7858   arrIo->alloc((int)(sz+1),1);
7859   int idsIt=idsOfSelectStart;
7860   int *work=arrIo->getPointer();
7861   *work++=0;
7862   int lgth=0;
7863   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
7864     {
7865       if(idsIt>=0 && idsIt<nbOfGrps)
7866         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
7867       else
7868         {
7869           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7870           throw INTERP_KERNEL::Exception(oss.str());
7871         }
7872       if(lgth>=work[-1])
7873         *work=lgth;
7874       else
7875         {
7876           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
7877           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
7878           throw INTERP_KERNEL::Exception(oss.str());
7879         }
7880     }
7881   arro->alloc(lgth,1);
7882   work=arro->getPointer();
7883   idsIt=idsOfSelectStart;
7884   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
7885     {
7886       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
7887         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
7888       else
7889         {
7890           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
7891           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7892           throw INTERP_KERNEL::Exception(oss.str());
7893         }
7894     }
7895   arrOut=arro.retn();
7896   arrIndexOut=arrIo.retn();
7897 }
7898
7899 /*!
7900  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7901  * 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
7902  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7903  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7904  *
7905  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7906  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7907  * \param [in] arrIn arr origin array from which the extraction will be done.
7908  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7909  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
7910  * \param [in] srcArrIndex index array of \b srcArr
7911  * \param [out] arrOut the resulting array
7912  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7913  * 
7914  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7915  */
7916 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7917                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7918                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7919 {
7920   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7921     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7922   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7923   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7924   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7925   std::vector<bool> v(nbOfTuples,true);
7926   int offset=0;
7927   const int *arrIndxInPtr=arrIndxIn->begin();
7928   const int *srcArrIndexPtr=srcArrIndex->begin();
7929   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7930     {
7931       if(*it>=0 && *it<nbOfTuples)
7932         {
7933           v[*it]=false;
7934           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7935         }
7936       else
7937         {
7938           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7939           throw INTERP_KERNEL::Exception(oss.str());
7940         }
7941     }
7942   srcArrIndexPtr=srcArrIndex->begin();
7943   arrIo->alloc(nbOfTuples+1,1);
7944   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7945   const int *arrInPtr=arrIn->begin();
7946   const int *srcArrPtr=srcArr->begin();
7947   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7948   int *arroPtr=arro->getPointer();
7949   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7950     {
7951       if(v[ii])
7952         {
7953           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7954           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7955         }
7956       else
7957         {
7958           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7959           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7960           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7961         }
7962     }
7963   arrOut=arro.retn();
7964   arrIndexOut=arrIo.retn();
7965 }
7966
7967 /*!
7968  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7969  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7970  *
7971  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7972  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7973  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7974  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7975  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
7976  * \param [in] srcArrIndex index array of \b srcArr
7977  * 
7978  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
7979  */
7980 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7981                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
7982 {
7983   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7984     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7985   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7986   const int *arrIndxInPtr=arrIndxIn->begin();
7987   const int *srcArrIndexPtr=srcArrIndex->begin();
7988   int *arrInOutPtr=arrInOut->getPointer();
7989   const int *srcArrPtr=srcArr->begin();
7990   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7991     {
7992       if(*it>=0 && *it<nbOfTuples)
7993         {
7994           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7995             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7996           else
7997             {
7998               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] !";
7999               throw INTERP_KERNEL::Exception(oss.str());
8000             }
8001         }
8002       else
8003         {
8004           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8005           throw INTERP_KERNEL::Exception(oss.str());
8006         }
8007     }
8008 }
8009
8010 /*!
8011  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8012  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8013  * 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]].
8014  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8015  * A negative value in \b arrIn means that it is ignored.
8016  * 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.
8017  * 
8018  * \param [in] arrIn arr origin array from which the extraction will be done.
8019  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8020  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8021  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8022  */
8023 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8024 {
8025   int seed=0,nbOfDepthPeelingPerformed=0;
8026   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8027 }
8028
8029 /*!
8030  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8031  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8032  * 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]].
8033  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8034  * A negative value in \b arrIn means that it is ignored.
8035  * 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.
8036  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8037  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8038  * \param [in] arrIn arr origin array from which the extraction will be done.
8039  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8040  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8041  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8042  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8043  * \sa MEDCouplingUMesh::partitionBySpreadZone
8044  */
8045 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
8046 {
8047   nbOfDepthPeelingPerformed=0;
8048   if(!arrIndxIn)
8049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8050   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8051   if(nbOfTuples<=0)
8052     {
8053       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8054       return ret;
8055     }
8056   //
8057   std::vector<bool> fetched(nbOfTuples,false);
8058   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8059 }
8060
8061
8062 /*!
8063  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8064  * 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
8065  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8066  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8067  *
8068  * \param [in] start begin of set of ids of the input extraction (included)
8069  * \param [in] end end of set of ids of the input extraction (excluded)
8070  * \param [in] step step of the set of ids in range mode.
8071  * \param [in] arrIn arr origin array from which the extraction will be done.
8072  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8073  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8074  * \param [in] srcArrIndex index array of \b srcArr
8075  * \param [out] arrOut the resulting array
8076  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8077  * 
8078  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8079  */
8080 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8081                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8082                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
8083 {
8084   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8085     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
8086   MCAuto<DataArrayInt> arro=DataArrayInt::New();
8087   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
8088   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8089   int offset=0;
8090   const int *arrIndxInPtr=arrIndxIn->begin();
8091   const int *srcArrIndexPtr=srcArrIndex->begin();
8092   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
8093   int it=start;
8094   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8095     {
8096       if(it>=0 && it<nbOfTuples)
8097         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8098       else
8099         {
8100           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8101           throw INTERP_KERNEL::Exception(oss.str());
8102         }
8103     }
8104   srcArrIndexPtr=srcArrIndex->begin();
8105   arrIo->alloc(nbOfTuples+1,1);
8106   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8107   const int *arrInPtr=arrIn->begin();
8108   const int *srcArrPtr=srcArr->begin();
8109   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8110   int *arroPtr=arro->getPointer();
8111   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8112     {
8113       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8114       if(pos<0)
8115         {
8116           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8117           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8118         }
8119       else
8120         {
8121           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8122           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8123         }
8124     }
8125   arrOut=arro.retn();
8126   arrIndexOut=arrIo.retn();
8127 }
8128
8129 /*!
8130  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8131  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8132  *
8133  * \param [in] start begin of set of ids of the input extraction (included)
8134  * \param [in] end end of set of ids of the input extraction (excluded)
8135  * \param [in] step step of the set of ids in range mode.
8136  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8137  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8138  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8139  * \param [in] srcArrIndex index array of \b srcArr
8140  * 
8141  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8142  */
8143 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8144                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
8145 {
8146   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8147     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
8148   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8149   const int *arrIndxInPtr=arrIndxIn->begin();
8150   const int *srcArrIndexPtr=srcArrIndex->begin();
8151   int *arrInOutPtr=arrInOut->getPointer();
8152   const int *srcArrPtr=srcArr->begin();
8153   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
8154   int it=start;
8155   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8156     {
8157       if(it>=0 && it<nbOfTuples)
8158         {
8159           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
8160             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
8161           else
8162             {
8163               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8164               throw INTERP_KERNEL::Exception(oss.str());
8165             }
8166         }
8167       else
8168         {
8169           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8170           throw INTERP_KERNEL::Exception(oss.str());
8171         }
8172     }
8173 }
8174
8175 /*!
8176  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8177  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8178  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8179  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8180  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8181  * 
8182  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8183  */
8184 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
8185 {
8186   checkFullyDefined();
8187   int mdim=getMeshDimension();
8188   int spaceDim=getSpaceDimension();
8189   if(mdim!=spaceDim)
8190     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8191   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8192   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8193   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
8194   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8195   ret->setCoords(getCoords());
8196   ret->allocateCells((int)partition.size());
8197   //
8198   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8199     {
8200       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8201       MCAuto<DataArrayInt> cell;
8202       switch(mdim)
8203       {
8204         case 2:
8205           cell=tmp->buildUnionOf2DMesh();
8206           break;
8207         case 3:
8208           cell=tmp->buildUnionOf3DMesh();
8209           break;
8210         default:
8211           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8212       }
8213
8214       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->begin()+1);
8215     }
8216   //
8217   ret->finishInsertingCells();
8218   return ret.retn();
8219 }
8220
8221 /*!
8222  * This method partitions \b this into contiguous zone.
8223  * This method only needs a well defined connectivity. Coordinates are not considered here.
8224  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8225  */
8226 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
8227 {
8228   DataArrayInt *neigh=0,*neighI=0;
8229   computeNeighborsOfCells(neigh,neighI);
8230   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8231   return PartitionBySpreadZone(neighAuto,neighIAuto);
8232 }
8233
8234 std::vector<DataArrayInt *> MEDCouplingUMesh::PartitionBySpreadZone(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8235 {
8236   if(!arrIn || !arrIndxIn)
8237     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : null input pointers !");
8238   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8239   int nbOfTuples(arrIndxIn->getNumberOfTuples());
8240   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1 || nbOfTuples<1)
8241     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : invalid arrays in input !");
8242   int nbOfCellsCur(nbOfTuples-1);
8243   std::vector<DataArrayInt *> ret;
8244   if(nbOfCellsCur<=0)
8245     return ret;
8246   std::vector<bool> fetchedCells(nbOfCellsCur,false);
8247   std::vector< MCAuto<DataArrayInt> > ret2;
8248   int seed=0;
8249   while(seed<nbOfCellsCur)
8250     {
8251       int nbOfPeelPerformed=0;
8252       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfPeelPerformed));
8253       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8254     }
8255   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8256     ret.push_back((*it).retn());
8257   return ret;
8258 }
8259
8260 /*!
8261  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8262  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8263  *
8264  * \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.
8265  * \return a newly allocated DataArrayInt to be managed by the caller.
8266  * \throw In case of \a code has not the right format (typically of size 3*n)
8267  */
8268 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
8269 {
8270   MCAuto<DataArrayInt> ret=DataArrayInt::New();
8271   std::size_t nb=code.size()/3;
8272   if(code.size()%3!=0)
8273     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8274   ret->alloc((int)nb,2);
8275   int *retPtr=ret->getPointer();
8276   for(std::size_t i=0;i<nb;i++,retPtr+=2)
8277     {
8278       retPtr[0]=code[3*i+2];
8279       retPtr[1]=code[3*i+2]+code[3*i+1];
8280     }
8281   return ret.retn();
8282 }
8283
8284 /*!
8285  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
8286  * All cells in \a this are expected to be linear 3D cells.
8287  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
8288  * It leads to an increase to number of cells.
8289  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
8290  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
8291  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
8292  *
8293  * \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.
8294  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
8295  * \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. 
8296  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
8297  *          an id of old cell producing it. The caller is to delete this array using
8298  *         decrRef() as it is no more needed.
8299  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
8300  *
8301  * \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
8302  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
8303  * 
8304  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
8305  * \throw If \a this is not fully constituted with linear 3D cells.
8306  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
8307  */
8308 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
8309 {
8310   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
8311   checkConnectivityFullyDefined();
8312   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
8314   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
8315   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
8316   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
8317   int *retPt(ret->getPointer());
8318   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
8319   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
8320   const int *oldc(_nodal_connec->begin());
8321   const int *oldci(_nodal_connec_index->begin());
8322   const double *coords(_coords->begin());
8323   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
8324     {
8325       std::vector<int> a; std::vector<double> b;
8326       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
8327       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
8328       const int *aa(&a[0]);
8329       if(!b.empty())
8330         {
8331           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
8332             if(*it<0)
8333               *it=(-(*(it))-1+nbNodes);
8334           addPts->insertAtTheEnd(b.begin(),b.end());
8335           nbNodes+=(int)b.size()/3;
8336         }
8337       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
8338         newConn->insertAtTheEnd(aa,aa+4);
8339     }
8340   if(!addPts->empty())
8341     {
8342       addPts->rearrange(3);
8343       nbOfAdditionalPoints=addPts->getNumberOfTuples();
8344       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
8345       ret0->setCoords(addPts);
8346     }
8347   else
8348     {
8349       nbOfAdditionalPoints=0;
8350       ret0->setCoords(getCoords());
8351     }
8352   ret0->setNodalConnectivity(newConn);
8353   //
8354   ret->computeOffsetsFull();
8355   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
8356   return ret0.retn();
8357 }
8358
8359 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8360     _own_cell(true),_cell_id(-1),_nb_cell(0)
8361 {
8362   if(mesh)
8363     {
8364       mesh->incrRef();
8365       _nb_cell=mesh->getNumberOfCells();
8366     }
8367 }
8368
8369 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8370 {
8371   if(_mesh)
8372     _mesh->decrRef();
8373   if(_own_cell)
8374     delete _cell;
8375 }
8376
8377 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8378     _own_cell(false),_cell_id(bg-1),
8379     _nb_cell(end)
8380 {
8381   if(mesh)
8382     mesh->incrRef();
8383 }
8384
8385 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8386 {
8387   _cell_id++;
8388   if(_cell_id<_nb_cell)
8389     {
8390       _cell->next();
8391       return _cell;
8392     }
8393   else
8394     return 0;
8395 }
8396
8397 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8398 {
8399   if(_mesh)
8400     _mesh->incrRef();
8401 }
8402
8403 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8404 {
8405   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8406 }
8407
8408 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8409 {
8410   if(_mesh)
8411     _mesh->decrRef();
8412 }
8413
8414 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8415     _itc(itc),
8416     _bg(bg),_end(end)
8417 {
8418   if(_mesh)
8419     _mesh->incrRef();
8420 }
8421
8422 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8423 {
8424   if(_mesh)
8425     _mesh->decrRef();
8426 }
8427
8428 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8429 {
8430   return _type;
8431 }
8432
8433 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8434 {
8435   return _end-_bg;
8436 }
8437
8438 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8439 {
8440   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8441 }
8442
8443 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8444 {
8445   if(mesh)
8446     {
8447       mesh->incrRef();
8448       _nb_cell=mesh->getNumberOfCells();
8449     }
8450 }
8451
8452 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8453 {
8454   if(_mesh)
8455     _mesh->decrRef();
8456   delete _cell;
8457 }
8458
8459 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8460 {
8461   const int *c=_mesh->getNodalConnectivity()->begin();
8462   const int *ci=_mesh->getNodalConnectivityIndex()->begin();
8463   if(_cell_id<_nb_cell)
8464     {
8465       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8466       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
8467       int startId=_cell_id;
8468       _cell_id+=nbOfElems;
8469       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8470     }
8471   else
8472     return 0;
8473 }
8474
8475 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8476 {
8477   if(mesh)
8478     {
8479       _conn=mesh->getNodalConnectivity()->getPointer();
8480       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8481     }
8482 }
8483
8484 void MEDCouplingUMeshCell::next()
8485 {
8486   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8487     {
8488       _conn+=_conn_lgth;
8489       _conn_indx++;
8490     }
8491   _conn_lgth=_conn_indx[1]-_conn_indx[0];
8492 }
8493
8494 std::string MEDCouplingUMeshCell::repr() const
8495 {
8496   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8497     {
8498       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8499       oss << " : ";
8500       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8501       return oss.str();
8502     }
8503   else
8504     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8505 }
8506
8507 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8508 {
8509   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8510     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8511   else
8512     return INTERP_KERNEL::NORM_ERROR;
8513 }
8514
8515 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8516 {
8517   lgth=_conn_lgth;
8518   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8519     return _conn;
8520   else
8521     return 0;
8522 }