Salome HOME
b3f97635be2224306db62a4903177f0a87edaaf1
[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       {
979         if ((*it).empty())
980           neighIdx[1]=neighIdx[0];
981         else
982           neighIdx[1]=neighIdx[0]+(*it).size()-1;
983       }
984   }
985   neighbors=DataArrayInt::New(); neighbors->alloc(neighborsIdx->back(),1);
986   {
987     const int *neighIdx(neighborsIdx->begin());
988     int *neigh(neighbors->getPointer()),nodeId(0);
989     for(std::vector< std::set<int> >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++,nodeId++)
990       {
991         std::set<int> s(*it); s.erase(nodeId);
992         std::copy(s.begin(),s.end(),neigh+*neighIdx);
993       }
994   }
995 }
996
997 /*!
998  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
999  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1000  * array of cell ids. Pay attention that after conversion all algorithms work slower
1001  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1002  * conversion due presence of invalid ids in the array of cells to convert, as a
1003  * result \a this mesh contains some already converted elements. In this case the 2D
1004  * mesh remains valid but 3D mesh becomes \b inconsistent!
1005  *  \warning This method can significantly modify the order of geometric types in \a this,
1006  *          hence, to write this mesh to the MED file, its cells must be sorted using
1007  *          sortCellsInMEDFileFrmt().
1008  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1009  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1010  *         cellIdsToConvertBg.
1011  *  \throw If the coordinates array is not set.
1012  *  \throw If the nodal connectivity of cells is node defined.
1013  *  \throw If dimension of \a this mesh is not either 2 or 3.
1014  *
1015  *  \if ENABLE_EXAMPLES
1016  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1017  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1018  *  \endif
1019  */
1020 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1021 {
1022   checkFullyDefined();
1023   int dim=getMeshDimension();
1024   if(dim<2 || dim>3)
1025     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1026   int nbOfCells(getNumberOfCells());
1027   if(dim==2)
1028     {
1029       const int *connIndex=_nodal_connec_index->begin();
1030       int *conn=_nodal_connec->getPointer();
1031       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1032         {
1033           if(*iter>=0 && *iter<nbOfCells)
1034             {
1035               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1036               if(!cm.isQuadratic())
1037                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1038               else
1039                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1040             }
1041           else
1042             {
1043               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1044               oss << " in range [0," << nbOfCells << ") !";
1045               throw INTERP_KERNEL::Exception(oss.str());
1046             }
1047         }
1048     }
1049   else
1050     {
1051       int *connIndex(_nodal_connec_index->getPointer());
1052       const int *connOld(_nodal_connec->getConstPointer());
1053       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1054       std::vector<bool> toBeDone(nbOfCells,false);
1055       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1056         {
1057           if(*iter>=0 && *iter<nbOfCells)
1058             toBeDone[*iter]=true;
1059           else
1060             {
1061               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1062               oss << " in range [0," << nbOfCells << ") !";
1063               throw INTERP_KERNEL::Exception(oss.str());
1064             }
1065         }
1066       for(int cellId=0;cellId<nbOfCells;cellId++)
1067         {
1068           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1069           int lgthOld(posP1-pos-1);
1070           if(toBeDone[cellId])
1071             {
1072               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1073               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1074               int *tmp(new int[nbOfFaces*lgthOld+1]);
1075               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1076               for(unsigned j=0;j<nbOfFaces;j++)
1077                 {
1078                   INTERP_KERNEL::NormalizedCellType type;
1079                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1080                   work+=offset;
1081                   *work++=-1;
1082                 }
1083               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1084               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1085               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1086               delete [] tmp;
1087             }
1088           else
1089             {
1090               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1091               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1092             }
1093         }
1094       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1095     }
1096   computeTypes();
1097 }
1098
1099 /*!
1100  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1101  * polyhedrons (if \a this is a 3D mesh).
1102  *  \warning As this method is purely for user-friendliness and no optimization is
1103  *          done to avoid construction of a useless vector, this method can be costly
1104  *          in memory.
1105  *  \throw If the coordinates array is not set.
1106  *  \throw If the nodal connectivity of cells is node defined.
1107  *  \throw If dimension of \a this mesh is not either 2 or 3.
1108  */
1109 void MEDCouplingUMesh::convertAllToPoly()
1110 {
1111   int nbOfCells=getNumberOfCells();
1112   std::vector<int> cellIds(nbOfCells);
1113   for(int i=0;i<nbOfCells;i++)
1114     cellIds[i]=i;
1115   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1116 }
1117
1118 /*!
1119  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1120  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1121  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1122  * base facet of the volume and the second half of nodes describes an opposite facet
1123  * having the same number of nodes as the base one. This method converts such
1124  * connectivity to a valid polyhedral format where connectivity of each facet is
1125  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1126  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1127  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1128  * a correct orientation of the first facet of a polyhedron, else orientation of a
1129  * corrected cell is reverse.<br>
1130  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1131  * it releases the user from boring description of polyhedra connectivity in the valid
1132  * format.
1133  *  \throw If \a this->getMeshDimension() != 3.
1134  *  \throw If \a this->getSpaceDimension() != 3.
1135  *  \throw If the nodal connectivity of cells is not defined.
1136  *  \throw If the coordinates array is not set.
1137  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1138  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1139  *
1140  *  \if ENABLE_EXAMPLES
1141  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1142  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1143  *  \endif
1144  */
1145 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1146 {
1147   checkFullyDefined();
1148   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1149     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1150   int nbOfCells=getNumberOfCells();
1151   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1152   newCi->alloc(nbOfCells+1,1);
1153   int *newci=newCi->getPointer();
1154   const int *ci=_nodal_connec_index->getConstPointer();
1155   const int *c=_nodal_connec->getConstPointer();
1156   newci[0]=0;
1157   for(int i=0;i<nbOfCells;i++)
1158     {
1159       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1160       if(type==INTERP_KERNEL::NORM_POLYHED)
1161         {
1162           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1163             {
1164               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1165               throw INTERP_KERNEL::Exception(oss.str());
1166             }
1167           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1168           if(n2%2!=0)
1169             {
1170               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 !";
1171               throw INTERP_KERNEL::Exception(oss.str());
1172             }
1173           int n1=(int)(n2/2);
1174           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)
1175         }
1176       else
1177         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1178     }
1179   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1180   newC->alloc(newci[nbOfCells],1);
1181   int *newc=newC->getPointer();
1182   for(int i=0;i<nbOfCells;i++)
1183     {
1184       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1185       if(type==INTERP_KERNEL::NORM_POLYHED)
1186         {
1187           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1188           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1189           *newc++=-1;
1190           for(std::size_t j=0;j<n1;j++)
1191             {
1192               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1193               newc[n1+5*j]=-1;
1194               newc[n1+5*j+1]=c[ci[i]+1+j];
1195               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1196               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1197               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1198             }
1199           newc+=n1*6;
1200         }
1201       else
1202         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1203     }
1204   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1205   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1206 }
1207
1208
1209 /*!
1210  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1211  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1212  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1213  *          to write this mesh to the MED file, its cells must be sorted using
1214  *          sortCellsInMEDFileFrmt().
1215  * \warning Cells (and most notably polyhedrons) must be correctly oriented for this to work
1216  *          properly. See orientCorrectlyPolyhedrons() and arePolyhedronsNotCorrectlyOriented().
1217  * \return \c true if at least one cell has been converted, \c false else. In the
1218  *         last case the nodal connectivity remains unchanged.
1219  * \throw If the coordinates array is not set.
1220  * \throw If the nodal connectivity of cells is not defined.
1221  * \throw If \a this->getMeshDimension() < 0.
1222  */
1223 bool MEDCouplingUMesh::unPolyze()
1224 {
1225   checkFullyDefined();
1226   int mdim=getMeshDimension();
1227   if(mdim<0)
1228     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1229   if(mdim<=1)
1230     return false;
1231   int nbOfCells=getNumberOfCells();
1232   if(nbOfCells<1)
1233     return false;
1234   int initMeshLgth=getNodalConnectivityArrayLen();
1235   int *conn=_nodal_connec->getPointer();
1236   int *index=_nodal_connec_index->getPointer();
1237   int posOfCurCell=0;
1238   int newPos=0;
1239   int lgthOfCurCell;
1240   bool ret=false;
1241   for(int i=0;i<nbOfCells;i++)
1242     {
1243       lgthOfCurCell=index[i+1]-posOfCurCell;
1244       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1245       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1246       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1247       int newLgth;
1248       if(cm.isDynamic())
1249         {
1250           switch(cm.getDimension())
1251           {
1252             case 2:
1253               {
1254                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1255                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1256                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1257                 break;
1258               }
1259             case 3:
1260               {
1261                 int nbOfFaces,lgthOfPolyhConn;
1262                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1263                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1264                 break;
1265               }
1266             case 1:
1267               {
1268                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1269                 break;
1270               }
1271           }
1272           ret=ret || (newType!=type);
1273           conn[newPos]=newType;
1274           newPos+=newLgth+1;
1275           posOfCurCell=index[i+1];
1276           index[i+1]=newPos;
1277         }
1278       else
1279         {
1280           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1281           newPos+=lgthOfCurCell;
1282           posOfCurCell+=lgthOfCurCell;
1283           index[i+1]=newPos;
1284         }
1285     }
1286   if(newPos!=initMeshLgth)
1287     _nodal_connec->reAlloc(newPos);
1288   if(ret)
1289     computeTypes();
1290   return ret;
1291 }
1292
1293 /*!
1294  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1295  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1296  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1297  *
1298  * \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 
1299  *             precision.
1300  */
1301 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1302 {
1303   checkFullyDefined();
1304   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1305     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1306   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1307   coords->recenterForMaxPrecision(eps);
1308   //
1309   int nbOfCells=getNumberOfCells();
1310   const int *conn=_nodal_connec->getConstPointer();
1311   const int *index=_nodal_connec_index->getConstPointer();
1312   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1313   connINew->alloc(nbOfCells+1,1);
1314   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1315   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1316   MCAuto<DataArrayInt> E_Fi(DataArrayInt::New()), E_F(DataArrayInt::New()), F_Ei(DataArrayInt::New()), F_E(DataArrayInt::New());
1317   MCAuto<MEDCouplingUMesh> m_faces(buildDescendingConnectivity(E_F, E_Fi, F_E, F_Ei));
1318   bool changed=false;
1319   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1320     {
1321       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1322         {
1323           SimplifyPolyhedronCell(eps,coords, i,connNew, m_faces, E_Fi, E_F, F_Ei, F_E);
1324           changed=true;
1325         }
1326       else
1327         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1328       *connINewPtr=connNew->getNumberOfTuples();
1329     }
1330   if(changed)
1331     setConnectivity(connNew,connINew,false);
1332 }
1333
1334 /*!
1335  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1336  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1337  * the format of the returned DataArrayInt instance.
1338  * 
1339  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1340  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1341  */
1342 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1343 {
1344   checkConnectivityFullyDefined();
1345   const int *maxEltPt(std::max_element(_nodal_connec->begin(),_nodal_connec->end()));
1346   int maxElt(maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1);
1347   std::vector<bool> retS(maxElt,false);
1348   computeNodeIdsAlg(retS);
1349   return DataArrayInt::BuildListOfSwitchedOn(retS);
1350 }
1351
1352 /*!
1353  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1354  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1355  */
1356 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1357 {
1358   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1359   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1360   for(int i=0;i<nbOfCells;i++)
1361     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1362       if(conn[j]>=0)
1363         {
1364           if(conn[j]<nbOfNodes)
1365             nodeIdsInUse[conn[j]]=true;
1366           else
1367             {
1368               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1369               throw INTERP_KERNEL::Exception(oss.str());
1370             }
1371         }
1372 }
1373
1374 /// @cond INTERNAL
1375
1376 struct MEDCouplingAccVisit
1377 {
1378   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1379   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1380   int _new_nb_of_nodes;
1381 };
1382
1383 /// @endcond
1384
1385 /*!
1386  * Finds nodes not used in any cell and returns an array giving a new id to every node
1387  * by excluding the unused nodes, for which the array holds -1. The result array is
1388  * a mapping in "Old to New" mode. 
1389  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1390  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1391  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1392  *          if the node is unused or a new id else. The caller is to delete this
1393  *          array using decrRef() as it is no more needed.  
1394  *  \throw If the coordinates array is not set.
1395  *  \throw If the nodal connectivity of cells is not defined.
1396  *  \throw If the nodal connectivity includes an invalid id.
1397  *
1398  *  \if ENABLE_EXAMPLES
1399  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1400  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1401  *  \endif
1402  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1403  */
1404 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1405 {
1406   nbrOfNodesInUse=-1;
1407   int nbOfNodes(getNumberOfNodes());
1408   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1409   ret->alloc(nbOfNodes,1);
1410   int *traducer=ret->getPointer();
1411   std::fill(traducer,traducer+nbOfNodes,-1);
1412   int nbOfCells=getNumberOfCells();
1413   const int *connIndex=_nodal_connec_index->getConstPointer();
1414   const int *conn=_nodal_connec->getConstPointer();
1415   for(int i=0;i<nbOfCells;i++)
1416     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1417       if(conn[j]>=0)
1418         {
1419           if(conn[j]<nbOfNodes)
1420             traducer[conn[j]]=1;
1421           else
1422             {
1423               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1424               throw INTERP_KERNEL::Exception(oss.str());
1425             }
1426         }
1427   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1428   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1429   return ret.retn();
1430 }
1431
1432 /*!
1433  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1434  * For each cell in \b this the number of nodes constituting cell is computed.
1435  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1436  * So for pohyhedrons some nodes can be counted several times in the returned result.
1437  * 
1438  * \return a newly allocated array
1439  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1440  */
1441 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1442 {
1443   checkConnectivityFullyDefined();
1444   int nbOfCells=getNumberOfCells();
1445   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1446   ret->alloc(nbOfCells,1);
1447   int *retPtr=ret->getPointer();
1448   const int *conn=getNodalConnectivity()->getConstPointer();
1449   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1450   for(int i=0;i<nbOfCells;i++,retPtr++)
1451     {
1452       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1453         *retPtr=connI[i+1]-connI[i]-1;
1454       else
1455         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1456     }
1457   return ret.retn();
1458 }
1459
1460 /*!
1461  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1462  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1463  *
1464  * \return DataArrayInt * - new object to be deallocated by the caller.
1465  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1466  */
1467 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1468 {
1469   checkConnectivityFullyDefined();
1470   int nbOfCells=getNumberOfCells();
1471   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1472   ret->alloc(nbOfCells,1);
1473   int *retPtr=ret->getPointer();
1474   const int *conn=getNodalConnectivity()->getConstPointer();
1475   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1476   for(int i=0;i<nbOfCells;i++,retPtr++)
1477     {
1478       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1479       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1480         *retPtr=(int)s.size();
1481       else
1482         {
1483           s.erase(-1);
1484           *retPtr=(int)s.size();
1485         }
1486     }
1487   return ret.retn();
1488 }
1489
1490 /*!
1491  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1492  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1493  * 
1494  * \return a newly allocated array
1495  */
1496 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1497 {
1498   checkConnectivityFullyDefined();
1499   int nbOfCells=getNumberOfCells();
1500   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1501   ret->alloc(nbOfCells,1);
1502   int *retPtr=ret->getPointer();
1503   const int *conn=getNodalConnectivity()->getConstPointer();
1504   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1505   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1506     {
1507       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1508       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1509     }
1510   return ret.retn();
1511 }
1512
1513 /*!
1514  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1515  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1516  * array mean that the corresponding old node is no more used. 
1517  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1518  *           this->getNumberOfNodes() before call of this method. The caller is to
1519  *           delete this array using decrRef() as it is no more needed. 
1520  *  \throw If the coordinates array is not set.
1521  *  \throw If the nodal connectivity of cells is not defined.
1522  *  \throw If the nodal connectivity includes an invalid id.
1523  *  \sa areAllNodesFetched
1524  *
1525  *  \if ENABLE_EXAMPLES
1526  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1527  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1528  *  \endif
1529  */
1530 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1531 {
1532   return MEDCouplingPointSet::zipCoordsTraducer();
1533 }
1534
1535 /*!
1536  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1537  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1538  */
1539 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1540 {
1541   switch(compType)
1542   {
1543     case 0:
1544       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1545     case 1:
1546       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1547     case 2:
1548       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1549     case 3:
1550       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1551     case 7:
1552       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1553   }
1554   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1555 }
1556
1557 /*!
1558  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1559  */
1560 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1561 {
1562   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1563     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1564   return 0;
1565 }
1566
1567 /*!
1568  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1569  */
1570 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1571 {
1572   int sz=connI[cell1+1]-connI[cell1];
1573   if(sz==connI[cell2+1]-connI[cell2])
1574     {
1575       if(conn[connI[cell1]]==conn[connI[cell2]])
1576         {
1577           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1578           unsigned dim=cm.getDimension();
1579           if(dim!=3)
1580             {
1581               if(dim!=1)
1582                 {
1583                   int sz1=2*(sz-1);
1584                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1585                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1586                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1587                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1588                   return work!=tmp+sz1?1:0;
1589                 }
1590               else
1591                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1592             }
1593           else
1594             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1595         }
1596     }
1597   return 0;
1598 }
1599
1600 /*!
1601  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1602  */
1603 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1604 {
1605   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1606     {
1607       if(conn[connI[cell1]]==conn[connI[cell2]])
1608         {
1609           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1610           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1611           return s1==s2?1:0;
1612         }
1613     }
1614   return 0;
1615 }
1616
1617 /*!
1618  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1619  */
1620 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1621 {
1622   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1623     {
1624       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1625       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1626       return s1==s2?1:0;
1627     }
1628   return 0;
1629 }
1630
1631 /*!
1632  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1633  */
1634 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1635 {
1636   int sz=connI[cell1+1]-connI[cell1];
1637   if(sz==connI[cell2+1]-connI[cell2])
1638     {
1639       if(conn[connI[cell1]]==conn[connI[cell2]])
1640         {
1641           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1642           unsigned dim=cm.getDimension();
1643           if(dim!=3)
1644             {
1645               if(dim!=1)
1646                 {
1647                   int sz1=2*(sz-1);
1648                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1649                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1650                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1651                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1652                   if(work!=tmp+sz1)
1653                     return 1;
1654                   else
1655                     {
1656                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1657                       std::reverse_iterator<int *> it2((int *)tmp);
1658                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1659                         return 2;
1660                       else
1661                         return 0;
1662                     }
1663
1664                   return work!=tmp+sz1?1:0;
1665                 }
1666               else
1667                 {//case of SEG2 and SEG3
1668                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1669                     return 1;
1670                   if(!cm.isQuadratic())
1671                     {
1672                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1673                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1674                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1675                         return 2;
1676                       return 0;
1677                     }
1678                   else
1679                     {
1680                       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])
1681                         return 2;
1682                       return 0;
1683                     }
1684                 }
1685             }
1686           else
1687             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1688         }
1689     }
1690   return 0;
1691 }
1692
1693
1694 /*!
1695  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1696  * by \a compType.
1697  * This method keeps the coordiantes of \a this. This method is time consuming.
1698  *
1699  * \param [in] compType input specifying the technique used to compare cells each other.
1700  *   - 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.
1701  *   - 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)
1702  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1703  *   - 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
1704  * can be used for users not sensitive to orientation of cell
1705  * \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.
1706  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1707  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1708  * \return the correspondance array old to new in a newly allocated array.
1709  * 
1710  */
1711 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1712 {
1713   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1714   getReverseNodalConnectivity(revNodal,revNodalI);
1715   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1716 }
1717
1718 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1719                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1720 {
1721   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1722   int nbOfCells=nodalI->getNumberOfTuples()-1;
1723   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1724   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1725   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1726   std::vector<bool> isFetched(nbOfCells,false);
1727   if(startCellId==0)
1728     {
1729       for(int i=0;i<nbOfCells;i++)
1730         {
1731           if(!isFetched[i])
1732             {
1733               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1734               std::vector<int> v,v2;
1735               if(connOfNode!=connPtr+connIPtr[i+1])
1736                 {
1737                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1738                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1739                   connOfNode++;
1740                 }
1741               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1742                 if(*connOfNode>=0)
1743                   {
1744                     v=v2;
1745                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1746                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1747                     v2.resize(std::distance(v2.begin(),it));
1748                   }
1749               if(v2.size()>1)
1750                 {
1751                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1752                     {
1753                       int pos=commonCellsI->back();
1754                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1755                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1756                         isFetched[*it]=true;
1757                     }
1758                 }
1759             }
1760         }
1761     }
1762   else
1763     {
1764       for(int i=startCellId;i<nbOfCells;i++)
1765         {
1766           if(!isFetched[i])
1767             {
1768               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1769               std::vector<int> v,v2;
1770               if(connOfNode!=connPtr+connIPtr[i+1])
1771                 {
1772                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1773                   connOfNode++;
1774                 }
1775               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1776                 if(*connOfNode>=0)
1777                   {
1778                     v=v2;
1779                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1780                     v2.resize(std::distance(v2.begin(),it));
1781                   }
1782               if(v2.size()>1)
1783                 {
1784                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1785                     {
1786                       int pos=commonCellsI->back();
1787                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1788                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1789                         isFetched[*it]=true;
1790                     }
1791                 }
1792             }
1793         }
1794     }
1795   commonCellsArr=commonCells.retn();
1796   commonCellsIArr=commonCellsI.retn();
1797 }
1798
1799 /*!
1800  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1801  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1802  * than \a this->getNumberOfCells() in the returned array means that there is no
1803  * corresponding cell in \a this mesh.
1804  * It is expected that \a this and \a other meshes share the same node coordinates
1805  * array, if it is not so an exception is thrown. 
1806  *  \param [in] other - the mesh to compare with.
1807  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1808  *         valid values [0,1,2], see zipConnectivityTraducer().
1809  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1810  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1811  *         values. The caller is to delete this array using
1812  *         decrRef() as it is no more needed.
1813  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1814  *         mesh.
1815  *
1816  *  \if ENABLE_EXAMPLES
1817  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1818  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1819  *  \endif
1820  *  \sa checkDeepEquivalOnSameNodesWith()
1821  *  \sa checkGeoEquivalWith()
1822  */
1823 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1824 {
1825   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1826   int nbOfCells=getNumberOfCells();
1827   static const int possibleCompType[]={0,1,2};
1828   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1829     {
1830       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1831       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1832       oss << " !";
1833       throw INTERP_KERNEL::Exception(oss.str());
1834     }
1835   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1836   arr=o2n->subArray(nbOfCells);
1837   arr->setName(other->getName());
1838   int tmp;
1839   if(other->getNumberOfCells()==0)
1840     return true;
1841   return arr->getMaxValue(tmp)<nbOfCells;
1842 }
1843
1844 /*!
1845  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1846  * This method tries to determine if \b other is fully included in \b this.
1847  * The main difference is that this method is not expected to throw exception.
1848  * This method has two outputs :
1849  *
1850  * \param other other mesh
1851  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1852  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1853  */
1854 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1855 {
1856   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1857   DataArrayInt *commonCells=0,*commonCellsI=0;
1858   int thisNbCells=getNumberOfCells();
1859   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1860   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1861   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1862   int otherNbCells=other->getNumberOfCells();
1863   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1864   arr2->alloc(otherNbCells,1);
1865   arr2->fillWithZero();
1866   int *arr2Ptr=arr2->getPointer();
1867   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1868   for(int i=0;i<nbOfCommon;i++)
1869     {
1870       int start=commonCellsPtr[commonCellsIPtr[i]];
1871       if(start<thisNbCells)
1872         {
1873           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1874             {
1875               int sig=commonCellsPtr[j]>0?1:-1;
1876               int val=std::abs(commonCellsPtr[j])-1;
1877               if(val>=thisNbCells)
1878                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1879             }
1880         }
1881     }
1882   arr2->setName(other->getName());
1883   if(arr2->presenceOfValue(0))
1884     return false;
1885   arr=arr2.retn();
1886   return true;
1887 }
1888
1889 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1890 {
1891   if(!other)
1892     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1893   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1894   if(!otherC)
1895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1896   std::vector<const MEDCouplingUMesh *> ms(2);
1897   ms[0]=this;
1898   ms[1]=otherC;
1899   return MergeUMeshesOnSameCoords(ms);
1900 }
1901
1902 /*!
1903  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1904  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1905  * cellIds is not given explicitely but by a range python like.
1906  * 
1907  * \param start
1908  * \param end
1909  * \param step
1910  * \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.
1911  * \return a newly allocated
1912  * 
1913  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1914  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1915  */
1916 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
1917 {
1918   if(getMeshDimension()!=-1)
1919     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
1920   else
1921     {
1922       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
1923       if(newNbOfCells!=1)
1924         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1925       if(start!=0)
1926         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1927       incrRef();
1928       return const_cast<MEDCouplingUMesh *>(this);
1929     }
1930 }
1931
1932 /*!
1933  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1934  * The result mesh shares or not the node coordinates array with \a this mesh depending
1935  * on \a keepCoords parameter.
1936  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1937  *           to write this mesh to the MED file, its cells must be sorted using
1938  *           sortCellsInMEDFileFrmt().
1939  *  \param [in] begin - an array of cell ids to include to the new mesh.
1940  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1941  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1942  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1943  *         by calling zipCoords().
1944  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
1945  *         to delete this mesh using decrRef() as it is no more needed. 
1946  *  \throw If the coordinates array is not set.
1947  *  \throw If the nodal connectivity of cells is not defined.
1948  *  \throw If any cell id in the array \a begin is not valid.
1949  *
1950  *  \if ENABLE_EXAMPLES
1951  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1952  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1953  *  \endif
1954  */
1955 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1956 {
1957   if(getMeshDimension()!=-1)
1958     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
1959   else
1960     {
1961       if(end-begin!=1)
1962         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1963       if(begin[0]!=0)
1964         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1965       incrRef();
1966       return const_cast<MEDCouplingUMesh *>(this);
1967     }
1968 }
1969
1970 /*!
1971  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1972  *
1973  * 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.
1974  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1975  * The number of cells of \b this will remain the same with this method.
1976  *
1977  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
1978  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
1979  * \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 ).
1980  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1981  */
1982 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1983 {
1984   checkConnectivityFullyDefined();
1985   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1986   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1987     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1988   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1989     {
1990       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1991       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1992       throw INTERP_KERNEL::Exception(oss.str());
1993     }
1994   std::size_t nbOfCellsToModify(std::distance(cellIdsBg,cellIdsEnd));
1995   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1996     {
1997       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1998       throw INTERP_KERNEL::Exception(oss.str());
1999     }
2000   std::size_t nbOfCells(getNumberOfCells());
2001   bool easyAssign(true);
2002   const int *connI(_nodal_connec_index->begin());
2003   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->begin();
2004   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2005     {
2006       if(*it>=0 && *it<(int)nbOfCells)
2007         {
2008           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2009         }
2010       else
2011         {
2012           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2013           throw INTERP_KERNEL::Exception(oss.str());
2014         }
2015     }
2016   if(easyAssign)
2017     {
2018       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2019       computeTypes();
2020     }
2021   else
2022     {
2023       DataArrayInt *arrOut=0,*arrIOut=0;
2024       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2025                                                arrOut,arrIOut);
2026       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2027       setConnectivity(arrOut,arrIOut,true);
2028     }
2029 }
2030
2031 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2032 {
2033   checkConnectivityFullyDefined();
2034   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2035   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2036     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2037   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2038     {
2039       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2040       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2041       throw INTERP_KERNEL::Exception(oss.str());
2042     }
2043   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2044   if(nbOfCellsToModify!=(int)otherOnSameCoordsThanThis.getNumberOfCells())
2045     {
2046       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2047       throw INTERP_KERNEL::Exception(oss.str());
2048     }
2049   int nbOfCells=getNumberOfCells();
2050   bool easyAssign=true;
2051   const int *connI=_nodal_connec_index->getConstPointer();
2052   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2053   int it=start;
2054   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2055     {
2056       if(it>=0 && it<nbOfCells)
2057         {
2058           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2059         }
2060       else
2061         {
2062           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2063           throw INTERP_KERNEL::Exception(oss.str());
2064         }
2065     }
2066   if(easyAssign)
2067     {
2068       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2069       computeTypes();
2070     }
2071   else
2072     {
2073       DataArrayInt *arrOut=0,*arrIOut=0;
2074       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2075                                                 arrOut,arrIOut);
2076       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2077       setConnectivity(arrOut,arrIOut,true);
2078     }
2079 }                      
2080
2081
2082 /*!
2083  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2084  * this->getMeshDimension(), that bound some cells of \a this mesh.
2085  * The cells of lower dimension to include to the result mesh are selected basing on
2086  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2087  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2088  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2089  * created mesh shares the node coordinates array with \a this mesh. 
2090  *  \param [in] begin - the array of node ids.
2091  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2092  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2093  *         array \a begin are added, else cells whose any node is in the
2094  *         array \a begin are added.
2095  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2096  *         to delete this mesh using decrRef() as it is no more needed. 
2097  *  \throw If the coordinates array is not set.
2098  *  \throw If the nodal connectivity of cells is not defined.
2099  *  \throw If any node id in \a begin is not valid.
2100  *
2101  *  \if ENABLE_EXAMPLES
2102  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2103  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2104  *  \endif
2105  */
2106 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2107 {
2108   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2109   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2110   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2111   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2112   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2113 }
2114
2115 /*!
2116  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2117  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2118  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2119  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2120  *         by calling zipCoords().
2121  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2122  *         to delete this mesh using decrRef() as it is no more needed. 
2123  *  \throw If the coordinates array is not set.
2124  *  \throw If the nodal connectivity of cells is not defined.
2125  *
2126  *  \if ENABLE_EXAMPLES
2127  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2128  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2129  *  \endif
2130  */
2131 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2132 {
2133   DataArrayInt *desc=DataArrayInt::New();
2134   DataArrayInt *descIndx=DataArrayInt::New();
2135   DataArrayInt *revDesc=DataArrayInt::New();
2136   DataArrayInt *revDescIndx=DataArrayInt::New();
2137   //
2138   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2139   revDesc->decrRef();
2140   desc->decrRef();
2141   descIndx->decrRef();
2142   int nbOfCells=meshDM1->getNumberOfCells();
2143   const int *revDescIndxC=revDescIndx->getConstPointer();
2144   std::vector<int> boundaryCells;
2145   for(int i=0;i<nbOfCells;i++)
2146     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2147       boundaryCells.push_back(i);
2148   revDescIndx->decrRef();
2149   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2150   return ret;
2151 }
2152
2153 /*!
2154  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2155  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2156  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2157  */
2158 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2159 {
2160   checkFullyDefined();
2161   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2162   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2163   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2164   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2165   //
2166   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2167   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2168   //
2169   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2170   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2171   const int *revDescPtr=revDesc->getConstPointer();
2172   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2173   int nbOfCells=getNumberOfCells();
2174   std::vector<bool> ret1(nbOfCells,false);
2175   int sz=0;
2176   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2177     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2178       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2179   //
2180   DataArrayInt *ret2=DataArrayInt::New();
2181   ret2->alloc(sz,1);
2182   int *ret2Ptr=ret2->getPointer();
2183   sz=0;
2184   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2185     if(*it)
2186       *ret2Ptr++=sz;
2187   ret2->setName("BoundaryCells");
2188   return ret2;
2189 }
2190
2191 /*!
2192  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2193  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2194  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2195  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2196  *
2197  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2198  * 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
2199  * equals a cell in \b otherDimM1OnSameCoords.
2200  *
2201  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2202  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2203  *
2204  * \param [in] otherDimM1OnSameCoords
2205  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2206  * \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
2207  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2208  */
2209 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2210 {
2211   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2212     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2213   checkConnectivityFullyDefined();
2214   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2215   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2216     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2217   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2218   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2219   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2220   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2221   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2222   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2223   DataArrayInt *idsOtherInConsti=0;
2224   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2225   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2226   if(!b)
2227     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2228   std::set<int> s1;
2229   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2230     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2231   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2232   s1arr_renum1->sort();
2233   cellIdsRk0=s0arr.retn();
2234   //cellIdsRk1=s_renum1.retn();
2235   cellIdsRk1=s1arr_renum1.retn();
2236 }
2237
2238 /*!
2239  * 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
2240  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2241  * 
2242  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2243  */
2244 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2245 {
2246   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2247   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2248   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2249   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2250   //
2251   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2252   revDesc=0; desc=0; descIndx=0;
2253   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2254   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2255   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2256 }
2257
2258 /*!
2259  * Finds nodes lying on the boundary of \a this mesh.
2260  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2261  *          nodes. The caller is to delete this array using decrRef() as it is no
2262  *          more needed.
2263  *  \throw If the coordinates array is not set.
2264  *  \throw If the nodal connectivity of cells is node defined.
2265  *
2266  *  \if ENABLE_EXAMPLES
2267  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2268  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2269  *  \endif
2270  */
2271 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2272 {
2273   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2274   return skin->computeFetchedNodeIds();
2275 }
2276
2277 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2278 {
2279   incrRef();
2280   return const_cast<MEDCouplingUMesh *>(this);
2281 }
2282
2283 /*!
2284  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2285  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2286  * 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.
2287  * 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.
2288  * 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.
2289  *
2290  * \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
2291  *             parameter is altered during the call.
2292  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2293  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2294  * \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.
2295  *
2296  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2297  */
2298 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2299                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2300 {
2301   typedef MCAuto<DataArrayInt> DAInt;
2302   typedef MCAuto<MEDCouplingUMesh> MCUMesh;
2303
2304   checkFullyDefined();
2305   otherDimM1OnSameCoords.checkFullyDefined();
2306   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2307     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2308   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2309     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2310
2311   // Checking star-shaped M1 group:
2312   DAInt dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2313   MCUMesh meshM2 = otherDimM1OnSameCoords.buildDescendingConnectivity(dt0, dit0, rdt0, rdit0);
2314   DAInt dsi = rdit0->deltaShiftIndex();
2315   DAInt idsTmp0 = dsi->findIdsNotInRange(-1, 3);
2316   if(idsTmp0->getNumberOfTuples())
2317     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group: group is too complex: some points (or edges) have more than two connected segments (or faces)!");
2318   dt0=0; dit0=0; rdt0=0; rdit0=0; idsTmp0=0;
2319
2320   // Get extreme nodes from the group (they won't be duplicated), ie nodes belonging to boundary cells of M1
2321   DAInt xtremIdsM2 = dsi->findIdsEqual(1); dsi = 0;
2322   MCUMesh meshM2Part = static_cast<MEDCouplingUMesh *>(meshM2->buildPartOfMySelf(xtremIdsM2->begin(), xtremIdsM2->end(),true));
2323   DAInt xtrem = meshM2Part->computeFetchedNodeIds();
2324   // Remove from the list points on the boundary of the M0 mesh (those need duplication!)
2325   dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2326   MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;
2327   dsi = rdit0->deltaShiftIndex();
2328   DAInt boundSegs = dsi->findIdsEqual(1);   // boundary segs/faces of the M0 mesh
2329   MCUMesh m0descSkin = static_cast<MEDCouplingUMesh *>(m0desc->buildPartOfMySelf(boundSegs->begin(),boundSegs->end(), true));
2330   DAInt fNodes = m0descSkin->computeFetchedNodeIds();
2331   // In 3D, some points on the boundary of M0 still need duplication:
2332   DAInt notDup = 0;
2333   if (getMeshDimension() == 3)
2334     {
2335       DAInt dnu1=DataArrayInt::New(), dnu2=DataArrayInt::New(), dnu3=DataArrayInt::New(), dnu4=DataArrayInt::New();
2336       MCUMesh m0descSkinDesc = m0descSkin->buildDescendingConnectivity(dnu1, dnu2, dnu3, dnu4);
2337       dnu1=0;dnu2=0;dnu3=0;dnu4=0;
2338       DataArrayInt * corresp=0;
2339       meshM2->areCellsIncludedIn(m0descSkinDesc,2,corresp);
2340       DAInt validIds = corresp->findIdsInRange(0, meshM2->getNumberOfCells());
2341       corresp->decrRef();
2342       if (validIds->getNumberOfTuples())
2343         {
2344           MCUMesh m1IntersecSkin = static_cast<MEDCouplingUMesh *>(m0descSkinDesc->buildPartOfMySelf(validIds->begin(), validIds->end(), true));
2345           DAInt notDuplSkin = m1IntersecSkin->findBoundaryNodes();
2346           DAInt fNodes1 = fNodes->buildSubstraction(notDuplSkin);
2347           notDup = xtrem->buildSubstraction(fNodes1);
2348         }
2349       else
2350         notDup = xtrem->buildSubstraction(fNodes);
2351     }
2352   else
2353     notDup = xtrem->buildSubstraction(fNodes);
2354
2355   // Now compute cells around group (i.e. cells where we will do the propagation to identify the two sub-sets delimited by the group)
2356   DAInt m1Nodes = otherDimM1OnSameCoords.computeFetchedNodeIds();
2357   DAInt dupl = m1Nodes->buildSubstraction(notDup);
2358   DAInt cellsAroundGroup = getCellIdsLyingOnNodes(dupl->begin(), dupl->end(), false);  // false= take cell in, even if not all nodes are in notDup
2359
2360   //
2361   MCUMesh m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true));
2362   int nCells2 = m0Part2->getNumberOfCells();
2363   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2364   MCUMesh m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2365
2366   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2367   DataArrayInt *tmp00=0,*tmp11=0;
2368   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2369   DAInt neighInit00(tmp00);
2370   DAInt neighIInit00(tmp11);
2371   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2372   DataArrayInt *idsTmp=0;
2373   m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2374   DAInt ids(idsTmp);
2375   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2376   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2377   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2378   DataArrayInt *tmp0=0,*tmp1=0;
2379   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2380   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2381   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2382   DAInt neigh00(tmp0);
2383   DAInt neighI00(tmp1);
2384
2385   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2386   int seed = 0, nIter = 0;
2387   int nIterMax = nCells2+1; // Safety net for the loop
2388   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2389   hitCells->fillWithValue(-1);
2390   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2391   cellsToModifyConn0_torenum->alloc(0,1);
2392   while (nIter < nIterMax)
2393     {
2394       DAInt t = hitCells->findIdsEqual(-1);
2395       if (!t->getNumberOfTuples())
2396         break;
2397       // Connex zone without the crack (to compute the next seed really)
2398       int dnu;
2399       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2400       std::size_t cnt(0);
2401       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2402         hitCells->setIJ(*ptr,0,1);
2403       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2404       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2405       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2406       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2407       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2408       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2409       DAInt intersec = nonHitCells->buildIntersection(comple);
2410       if (intersec->getNumberOfTuples())
2411         { seed = intersec->getIJ(0,0); }
2412       else
2413         { break; }
2414       nIter++;
2415     }
2416   if (nIter >= nIterMax)
2417     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2418
2419   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2420   cellsToModifyConn0_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2421   cellsToModifyConn1_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2422   //
2423   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2424   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2425   nodeIdsToDuplicate=dupl.retn();
2426 }
2427
2428 /*!
2429  * This method operates a modification of the connectivity and coords in \b this.
2430  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2431  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2432  * 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
2433  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2434  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2435  * 
2436  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2437  * 
2438  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2439  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2440  */
2441 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2442 {
2443   int nbOfNodes=getNumberOfNodes();
2444   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2445   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2446 }
2447
2448 /*!
2449  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2450  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2451  *
2452  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2453  *
2454  * \sa renumberNodesInConn
2455  */
2456 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2457 {
2458   checkConnectivityFullyDefined();
2459   int *conn(getNodalConnectivity()->getPointer());
2460   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2461   int nbOfCells(getNumberOfCells());
2462   for(int i=0;i<nbOfCells;i++)
2463     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2464       {
2465         int& node=conn[iconn];
2466         if(node>=0)//avoid polyhedron separator
2467           {
2468             node+=offset;
2469           }
2470       }
2471   _nodal_connec->declareAsNew();
2472   updateTime();
2473 }
2474
2475 /*!
2476  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2477  *  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
2478  *  of a big mesh.
2479  */
2480 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2481 {
2482   checkConnectivityFullyDefined();
2483   int *conn(getNodalConnectivity()->getPointer());
2484   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2485   int nbOfCells(getNumberOfCells());
2486   for(int i=0;i<nbOfCells;i++)
2487     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2488       {
2489         int& node=conn[iconn];
2490         if(node>=0)//avoid polyhedron separator
2491           {
2492             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2493             if(it!=newNodeNumbersO2N.end())
2494               {
2495                 node=(*it).second;
2496               }
2497             else
2498               {
2499                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2500                 throw INTERP_KERNEL::Exception(oss.str());
2501               }
2502           }
2503       }
2504   _nodal_connec->declareAsNew();
2505   updateTime();
2506 }
2507
2508 /*!
2509  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2510  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2511  * This method is a generalization of shiftNodeNumbersInConn().
2512  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2513  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2514  *         this->getNumberOfNodes(), in "Old to New" mode. 
2515  *         See \ref numbering for more info on renumbering modes.
2516  *  \throw If the nodal connectivity of cells is not defined.
2517  *
2518  *  \if ENABLE_EXAMPLES
2519  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2520  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2521  *  \endif
2522  */
2523 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2524 {
2525   checkConnectivityFullyDefined();
2526   int *conn=getNodalConnectivity()->getPointer();
2527   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2528   int nbOfCells(getNumberOfCells());
2529   for(int i=0;i<nbOfCells;i++)
2530     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2531       {
2532         int& node=conn[iconn];
2533         if(node>=0)//avoid polyhedron separator
2534           {
2535             node=newNodeNumbersO2N[node];
2536           }
2537       }
2538   _nodal_connec->declareAsNew();
2539   updateTime();
2540 }
2541
2542 /*!
2543  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2544  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2545  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2546  * 
2547  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2548  */
2549 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2550 {
2551   checkConnectivityFullyDefined();
2552   int *conn=getNodalConnectivity()->getPointer();
2553   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2554   int nbOfCells=getNumberOfCells();
2555   for(int i=0;i<nbOfCells;i++)
2556     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2557       {
2558         int& node=conn[iconn];
2559         if(node>=0)//avoid polyhedron separator
2560           {
2561             node+=delta;
2562           }
2563       }
2564   _nodal_connec->declareAsNew();
2565   updateTime();
2566 }
2567
2568 /*!
2569  * This method operates a modification of the connectivity in \b this.
2570  * 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.
2571  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2572  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2573  * 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
2574  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2575  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2576  * 
2577  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2578  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2579  * 
2580  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2581  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2582  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2583  */
2584 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2585 {
2586   checkConnectivityFullyDefined();
2587   std::map<int,int> m;
2588   int val=offset;
2589   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2590     m[*work]=val;
2591   int *conn=getNodalConnectivity()->getPointer();
2592   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2593   int nbOfCells=getNumberOfCells();
2594   for(int i=0;i<nbOfCells;i++)
2595     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2596       {
2597         int& node=conn[iconn];
2598         if(node>=0)//avoid polyhedron separator
2599           {
2600             std::map<int,int>::iterator it=m.find(node);
2601             if(it!=m.end())
2602               node=(*it).second;
2603           }
2604       }
2605   updateTime();
2606 }
2607
2608 /*!
2609  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2610  *
2611  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2612  * After the call of this method the number of cells remains the same as before.
2613  *
2614  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2615  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2616  * be strictly in [0;this->getNumberOfCells()).
2617  *
2618  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2619  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2620  * should be contained in[0;this->getNumberOfCells()).
2621  * 
2622  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2623  * \param check
2624  */
2625 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2626 {
2627   checkConnectivityFullyDefined();
2628   int nbCells=getNumberOfCells();
2629   const int *array=old2NewBg;
2630   if(check)
2631     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2632   //
2633   const int *conn=_nodal_connec->getConstPointer();
2634   const int *connI=_nodal_connec_index->getConstPointer();
2635   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2636   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2637   const int *n2oPtr=n2o->begin();
2638   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2639   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2640   newConn->copyStringInfoFrom(*_nodal_connec);
2641   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2642   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2643   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2644   //
2645   int *newC=newConn->getPointer();
2646   int *newCI=newConnI->getPointer();
2647   int loc=0;
2648   newCI[0]=loc;
2649   for(int i=0;i<nbCells;i++)
2650     {
2651       int pos=n2oPtr[i];
2652       int nbOfElts=connI[pos+1]-connI[pos];
2653       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2654       loc+=nbOfElts;
2655       newCI[i+1]=loc;
2656     }
2657   //
2658   setConnectivity(newConn,newConnI);
2659   if(check)
2660     free(const_cast<int *>(array));
2661 }
2662
2663 /*!
2664  * Finds cells whose bounding boxes intersect a given bounding box.
2665  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2666  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2667  *         zMax (if in 3D). 
2668  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2669  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2670  *         extent of the bounding box of cell to produce an addition to this bounding box.
2671  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2672  *         cells. The caller is to delete this array using decrRef() as it is no more
2673  *         needed. 
2674  *  \throw If the coordinates array is not set.
2675  *  \throw If the nodal connectivity of cells is not defined.
2676  *
2677  *  \if ENABLE_EXAMPLES
2678  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2679  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2680  *  \endif
2681  */
2682 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2683 {
2684   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2685   if(getMeshDimension()==-1)
2686     {
2687       elems->pushBackSilent(0);
2688       return elems.retn();
2689     }
2690   int dim=getSpaceDimension();
2691   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2692   const int* conn      = getNodalConnectivity()->getConstPointer();
2693   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2694   const double* coords = getCoords()->getConstPointer();
2695   int nbOfCells=getNumberOfCells();
2696   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2697     {
2698       for (int i=0; i<dim; i++)
2699         {
2700           elem_bb[i*2]=std::numeric_limits<double>::max();
2701           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2702         }
2703
2704       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2705         {
2706           int node= conn[inode];
2707           if(node>=0)//avoid polyhedron separator
2708             {
2709               for (int idim=0; idim<dim; idim++)
2710                 {
2711                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2712                     {
2713                       elem_bb[idim*2] = coords[node*dim+idim] ;
2714                     }
2715                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2716                     {
2717                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2718                     }
2719                 }
2720             }
2721         }
2722       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2723         elems->pushBackSilent(ielem);
2724     }
2725   return elems.retn();
2726 }
2727
2728 /*!
2729  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2730  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2731  * added in 'elems' parameter.
2732  */
2733 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2734 {
2735   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2736   if(getMeshDimension()==-1)
2737     {
2738       elems->pushBackSilent(0);
2739       return elems.retn();
2740     }
2741   int dim=getSpaceDimension();
2742   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2743   const int* conn      = getNodalConnectivity()->getConstPointer();
2744   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2745   const double* coords = getCoords()->getConstPointer();
2746   int nbOfCells=getNumberOfCells();
2747   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2748     {
2749       for (int i=0; i<dim; i++)
2750         {
2751           elem_bb[i*2]=std::numeric_limits<double>::max();
2752           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2753         }
2754
2755       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2756         {
2757           int node= conn[inode];
2758           if(node>=0)//avoid polyhedron separator
2759             {
2760               for (int idim=0; idim<dim; idim++)
2761                 {
2762                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2763                     {
2764                       elem_bb[idim*2] = coords[node*dim+idim] ;
2765                     }
2766                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2767                     {
2768                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2769                     }
2770                 }
2771             }
2772         }
2773       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2774         elems->pushBackSilent(ielem);
2775     }
2776   return elems.retn();
2777 }
2778
2779 /*!
2780  * Returns a type of a cell by its id.
2781  *  \param [in] cellId - the id of the cell of interest.
2782  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2783  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2784  */
2785 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(std::size_t cellId) const
2786 {
2787   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2788   if(cellId<_nodal_connec_index->getNbOfElems()-1)
2789     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2790   else
2791     {
2792       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2793       throw INTERP_KERNEL::Exception(oss.str());
2794     }
2795 }
2796
2797 /*!
2798  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2799  * This method does not throw exception if geometric type \a type is not in \a this.
2800  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2801  * The coordinates array is not considered here.
2802  *
2803  * \param [in] type the geometric type
2804  * \return cell ids in this having geometric type \a type.
2805  */
2806 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2807 {
2808
2809   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2810   ret->alloc(0,1);
2811   checkConnectivityFullyDefined();
2812   int nbCells=getNumberOfCells();
2813   int mdim=getMeshDimension();
2814   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2815   if(mdim!=(int)cm.getDimension())
2816     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2817   const int *ptI=_nodal_connec_index->getConstPointer();
2818   const int *pt=_nodal_connec->getConstPointer();
2819   for(int i=0;i<nbCells;i++)
2820     {
2821       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2822         ret->pushBackSilent(i);
2823     }
2824   return ret.retn();
2825 }
2826
2827 /*!
2828  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2829  */
2830 std::size_t MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2831 {
2832   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2833   std::size_t nbOfCells(getNumberOfCells()),ret(0);
2834   for(std::size_t i=0;i<nbOfCells;i++)
2835     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2836       ret++;
2837   return ret;
2838 }
2839
2840 /*!
2841  * Returns the nodal connectivity of a given cell.
2842  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2843  * all returned node ids can be used in getCoordinatesOfNode().
2844  *  \param [in] cellId - an id of the cell of interest.
2845  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2846  *         cleared before the appending.
2847  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2848  */
2849 void MEDCouplingUMesh::getNodeIdsOfCell(std::size_t cellId, std::vector<int>& conn) const
2850 {
2851   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2852   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2853     if(*w>=0)
2854       conn.push_back(*w);
2855 }
2856
2857 std::string MEDCouplingUMesh::simpleRepr() const
2858 {
2859   static const char msg0[]="No coordinates specified !";
2860   std::ostringstream ret;
2861   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2862   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2863   int tmpp1,tmpp2;
2864   double tt=getTime(tmpp1,tmpp2);
2865   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2866   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2867   if(_mesh_dim>=-1)
2868     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2869   else
2870     { ret << " Mesh dimension has not been set or is invalid !"; }
2871   if(_coords!=0)
2872     {
2873       const int spaceDim=getSpaceDimension();
2874       ret << spaceDim << "\nInfo attached on space dimension : ";
2875       for(int i=0;i<spaceDim;i++)
2876         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2877       ret << "\n";
2878     }
2879   else
2880     ret << msg0 << "\n";
2881   ret << "Number of nodes : ";
2882   if(_coords!=0)
2883     ret << getNumberOfNodes() << "\n";
2884   else
2885     ret << msg0 << "\n";
2886   ret << "Number of cells : ";
2887   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2888     ret << getNumberOfCells() << "\n";
2889   else
2890     ret << "No connectivity specified !" << "\n";
2891   ret << "Cell types present : ";
2892   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2893     {
2894       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2895       ret << cm.getRepr() << " ";
2896     }
2897   ret << "\n";
2898   return ret.str();
2899 }
2900
2901 std::string MEDCouplingUMesh::advancedRepr() const
2902 {
2903   std::ostringstream ret;
2904   ret << simpleRepr();
2905   ret << "\nCoordinates array : \n___________________\n\n";
2906   if(_coords)
2907     _coords->reprWithoutNameStream(ret);
2908   else
2909     ret << "No array set !\n";
2910   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2911   reprConnectivityOfThisLL(ret);
2912   return ret.str();
2913 }
2914
2915 /*!
2916  * This method returns a C++ code that is a dump of \a this.
2917  * This method will throw if this is not fully defined.
2918  */
2919 std::string MEDCouplingUMesh::cppRepr() const
2920 {
2921   static const char coordsName[]="coords";
2922   static const char connName[]="conn";
2923   static const char connIName[]="connI";
2924   checkFullyDefined();
2925   std::ostringstream ret; ret << "// coordinates" << std::endl;
2926   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2927   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2928   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2929   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2930   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2931   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2932   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2933   return ret.str();
2934 }
2935
2936 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2937 {
2938   std::ostringstream ret;
2939   reprConnectivityOfThisLL(ret);
2940   return ret.str();
2941 }
2942
2943 /*!
2944  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2945  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2946  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2947  * some algos).
2948  * 
2949  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2950  * 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
2951  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2952  */
2953 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2954 {
2955   int mdim=getMeshDimension();
2956   if(mdim<0)
2957     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2958   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2959   MCAuto<DataArrayInt> tmp1,tmp2;
2960   bool needToCpyCT=true;
2961   if(!_nodal_connec)
2962     {
2963       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2964       needToCpyCT=false;
2965     }
2966   else
2967     {
2968       tmp1=_nodal_connec;
2969       tmp1->incrRef();
2970     }
2971   if(!_nodal_connec_index)
2972     {
2973       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2974       needToCpyCT=false;
2975     }
2976   else
2977     {
2978       tmp2=_nodal_connec_index;
2979       tmp2->incrRef();
2980     }
2981   ret->setConnectivity(tmp1,tmp2,false);
2982   if(needToCpyCT)
2983     ret->_types=_types;
2984   if(!_coords)
2985     {
2986       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2987       ret->setCoords(coords);
2988     }
2989   else
2990     ret->setCoords(_coords);
2991   return ret.retn();
2992 }
2993
2994 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2995 {
2996   const int *ptI=_nodal_connec_index->getConstPointer();
2997   const int *pt=_nodal_connec->getConstPointer();
2998   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2999     return ptI[cellId+1]-ptI[cellId]-1;
3000   else
3001     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3002 }
3003
3004 /*!
3005  * Returns types of cells of the specified part of \a this mesh.
3006  * This method avoids computing sub-mesh explicitely to get its types.
3007  *  \param [in] begin - an array of cell ids of interest.
3008  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3009  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3010  *         describing the cell types. 
3011  *  \throw If the coordinates array is not set.
3012  *  \throw If the nodal connectivity of cells is not defined.
3013  *  \sa getAllGeoTypes()
3014  */
3015 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3016 {
3017   checkFullyDefined();
3018   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3019   const int *conn=_nodal_connec->getConstPointer();
3020   const int *connIndex=_nodal_connec_index->getConstPointer();
3021   for(const int *w=begin;w!=end;w++)
3022     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3023   return ret;
3024 }
3025
3026 /*!
3027  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3028  * Optionally updates
3029  * a set of types of cells constituting \a this mesh. 
3030  * This method is for advanced users having prepared their connectivity before. For
3031  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3032  *  \param [in] conn - the nodal connectivity array. 
3033  *  \param [in] connIndex - the nodal connectivity index array.
3034  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3035  *         mesh is updated.
3036  */
3037 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3038 {
3039   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3040   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3041   if(isComputingTypes)
3042     computeTypes();
3043   declareAsNew();
3044 }
3045
3046 /*!
3047  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3048  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3049  */
3050 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCpy):MEDCouplingPointSet(other,deepCpy),_mesh_dim(other._mesh_dim),
3051     _nodal_connec(0),_nodal_connec_index(0),
3052     _types(other._types)
3053 {
3054   if(other._nodal_connec)
3055     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCpy);
3056   if(other._nodal_connec_index)
3057     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCpy);
3058 }
3059
3060 MEDCouplingUMesh::~MEDCouplingUMesh()
3061 {
3062   if(_nodal_connec)
3063     _nodal_connec->decrRef();
3064   if(_nodal_connec_index)
3065     _nodal_connec_index->decrRef();
3066 }
3067
3068 /*!
3069  * Recomputes a set of cell types of \a this mesh. For more info see
3070  * \ref MEDCouplingUMeshNodalConnectivity.
3071  */
3072 void MEDCouplingUMesh::computeTypes()
3073 {
3074   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3075 }
3076
3077
3078 /*!
3079  * Returns a number of cells constituting \a this mesh. 
3080  *  \return int - the number of cells in \a this mesh.
3081  *  \throw If the nodal connectivity of cells is not defined.
3082  */
3083 std::size_t MEDCouplingUMesh::getNumberOfCells() const
3084
3085   if(_nodal_connec_index)
3086     return _nodal_connec_index->getNumberOfTuples()-1;
3087   else
3088     if(_mesh_dim==-1)
3089       return 1;
3090     else
3091       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3092 }
3093
3094 /*!
3095  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3096  * mesh. For more info see \ref meshes.
3097  *  \return int - the dimension of \a this mesh.
3098  *  \throw If the mesh dimension is not defined using setMeshDimension().
3099  */
3100 int MEDCouplingUMesh::getMeshDimension() const
3101 {
3102   if(_mesh_dim<-1)
3103     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3104   return _mesh_dim;
3105 }
3106
3107 /*!
3108  * Returns a length of the nodal connectivity array.
3109  * This method is for test reason. Normally the integer returned is not useable by
3110  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3111  *  \return int - the length of the nodal connectivity array.
3112  */
3113 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3114 {
3115   return _nodal_connec->getNbOfElems();
3116 }
3117
3118 /*!
3119  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3120  */
3121 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3122 {
3123   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3124   tinyInfo.push_back(getMeshDimension());
3125   tinyInfo.push_back(getNumberOfCells());
3126   if(_nodal_connec)
3127     tinyInfo.push_back(getNodalConnectivityArrayLen());
3128   else
3129     tinyInfo.push_back(-1);
3130 }
3131
3132 /*!
3133  * First step of unserialization process.
3134  */
3135 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3136 {
3137   return tinyInfo[6]<=0;
3138 }
3139
3140 /*!
3141  * Second step of serialization process.
3142  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3143  * \param a1
3144  * \param a2
3145  * \param littleStrings
3146  */
3147 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3148 {
3149   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3150   if(tinyInfo[5]!=-1)
3151     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3152 }
3153
3154 /*!
3155  * Third and final step of serialization process.
3156  */
3157 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3158 {
3159   MEDCouplingPointSet::serialize(a1,a2);
3160   if(getMeshDimension()>-1)
3161     {
3162       a1=DataArrayInt::New();
3163       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3164       int *ptA1=a1->getPointer();
3165       const int *conn=getNodalConnectivity()->getConstPointer();
3166       const int *index=getNodalConnectivityIndex()->getConstPointer();
3167       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3168       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3169     }
3170   else
3171     a1=0;
3172 }
3173
3174 /*!
3175  * Second and final unserialization process.
3176  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3177  */
3178 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3179 {
3180   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3181   setMeshDimension(tinyInfo[5]);
3182   if(tinyInfo[7]!=-1)
3183     {
3184       // Connectivity
3185       const int *recvBuffer=a1->getConstPointer();
3186       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3187       myConnecIndex->alloc(tinyInfo[6]+1,1);
3188       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3189       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3190       myConnec->alloc(tinyInfo[7],1);
3191       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3192       setConnectivity(myConnec, myConnecIndex);
3193     }
3194 }
3195
3196
3197
3198 /*!
3199  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3200  * mesh.<br>
3201  * For 1D cells, the returned field contains lengths.<br>
3202  * For 2D cells, the returned field contains areas.<br>
3203  * For 3D cells, the returned field contains volumes.
3204  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3205  *         orientation, i.e. the volume is always positive.
3206  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3207  *         and one time . The caller is to delete this field using decrRef() as it is no
3208  *         more needed.
3209  */
3210 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3211 {
3212   std::string name="MeasureOfMesh_";
3213   name+=getName();
3214   int nbelem=getNumberOfCells();
3215   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3216   field->setName(name);
3217   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3218   array->alloc(nbelem,1);
3219   double *area_vol=array->getPointer();
3220   field->setArray(array) ; array=0;
3221   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3222   field->synchronizeTimeWithMesh();
3223   if(getMeshDimension()!=-1)
3224     {
3225       int ipt;
3226       INTERP_KERNEL::NormalizedCellType type;
3227       int dim_space=getSpaceDimension();
3228       const double *coords=getCoords()->getConstPointer();
3229       const int *connec=getNodalConnectivity()->getConstPointer();
3230       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3231       for(int iel=0;iel<nbelem;iel++)
3232         {
3233           ipt=connec_index[iel];
3234           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3235           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);
3236         }
3237       if(isAbs)
3238         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3239     }
3240   else
3241     {
3242       area_vol[0]=std::numeric_limits<double>::max();
3243     }
3244   return field.retn();
3245 }
3246
3247 /*!
3248  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3249  * mesh.<br>
3250  * For 1D cells, the returned array contains lengths.<br>
3251  * For 2D cells, the returned array contains areas.<br>
3252  * For 3D cells, the returned array contains volumes.
3253  * This method avoids building explicitly a part of \a this mesh to perform the work.
3254  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3255  *         orientation, i.e. the volume is always positive.
3256  *  \param [in] begin - an array of cell ids of interest.
3257  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3258  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3259  *          delete this array using decrRef() as it is no more needed.
3260  * 
3261  *  \if ENABLE_EXAMPLES
3262  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3263  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3264  *  \endif
3265  *  \sa getMeasureField()
3266  */
3267 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3268 {
3269   std::string name="PartMeasureOfMesh_";
3270   name+=getName();
3271   int nbelem=(int)std::distance(begin,end);
3272   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3273   array->setName(name);
3274   array->alloc(nbelem,1);
3275   double *area_vol=array->getPointer();
3276   if(getMeshDimension()!=-1)
3277     {
3278       int ipt;
3279       INTERP_KERNEL::NormalizedCellType type;
3280       int dim_space=getSpaceDimension();
3281       const double *coords=getCoords()->getConstPointer();
3282       const int *connec=getNodalConnectivity()->getConstPointer();
3283       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3284       for(const int *iel=begin;iel!=end;iel++)
3285         {
3286           ipt=connec_index[*iel];
3287           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3288           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3289         }
3290       if(isAbs)
3291         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3292     }
3293   else
3294     {
3295       area_vol[0]=std::numeric_limits<double>::max();
3296     }
3297   return array.retn();
3298 }
3299
3300 /*!
3301  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3302  * \a this one. The returned field contains the dual cell volume for each corresponding
3303  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3304  *  the dual mesh in P1 sens of \a this.<br>
3305  * For 1D cells, the returned field contains lengths.<br>
3306  * For 2D cells, the returned field contains areas.<br>
3307  * For 3D cells, the returned field contains volumes.
3308  * This method is useful to check "P1*" conservative interpolators.
3309  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3310  *         orientation, i.e. the volume is always positive.
3311  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3312  *          nodes and one time. The caller is to delete this array using decrRef() as
3313  *          it is no more needed.
3314  */
3315 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3316 {
3317   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3318   std::string name="MeasureOnNodeOfMesh_";
3319   name+=getName();
3320   int nbNodes=getNumberOfNodes();
3321   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3322   double cst=1./((double)getMeshDimension()+1.);
3323   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3324   array->alloc(nbNodes,1);
3325   double *valsToFill=array->getPointer();
3326   std::fill(valsToFill,valsToFill+nbNodes,0.);
3327   const double *values=tmp->getArray()->getConstPointer();
3328   MCAuto<DataArrayInt> da=DataArrayInt::New();
3329   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3330   getReverseNodalConnectivity(da,daInd);
3331   const int *daPtr=da->getConstPointer();
3332   const int *daIPtr=daInd->getConstPointer();
3333   for(int i=0;i<nbNodes;i++)
3334     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3335       valsToFill[i]+=cst*values[*cell];
3336   ret->setMesh(this);
3337   ret->setArray(array);
3338   return ret.retn();
3339 }
3340
3341 /*!
3342  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3343  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3344  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3345  * and are normalized.
3346  * <br> \a this can be either 
3347  * - a  2D mesh in 2D or 3D space or 
3348  * - an 1D mesh in 2D space.
3349  * 
3350  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3351  *          cells and one time. The caller is to delete this field using decrRef() as
3352  *          it is no more needed.
3353  *  \throw If the nodal connectivity of cells is not defined.
3354  *  \throw If the coordinates array is not set.
3355  *  \throw If the mesh dimension is not set.
3356  *  \throw If the mesh and space dimension is not as specified above.
3357  */
3358 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3359 {
3360   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3361     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3362   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3363   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3364   int nbOfCells=getNumberOfCells();
3365   int nbComp=getMeshDimension()+1;
3366   array->alloc(nbOfCells,nbComp);
3367   double *vals=array->getPointer();
3368   const int *connI=_nodal_connec_index->getConstPointer();
3369   const int *conn=_nodal_connec->getConstPointer();
3370   const double *coords=_coords->getConstPointer();
3371   if(getMeshDimension()==2)
3372     {
3373       if(getSpaceDimension()==3)
3374         {
3375           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3376           const double *locPtr=loc->getConstPointer();
3377           for(int i=0;i<nbOfCells;i++,vals+=3)
3378             {
3379               int offset=connI[i];
3380               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3381               double n=INTERP_KERNEL::norm<3>(vals);
3382               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3383             }
3384         }
3385       else
3386         {
3387           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3388           const double *isAbsPtr=isAbs->getArray()->begin();
3389           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3390             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3391         }
3392     }
3393   else//meshdimension==1
3394     {
3395       double tmp[2];
3396       for(int i=0;i<nbOfCells;i++)
3397         {
3398           int offset=connI[i];
3399           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3400           double n=INTERP_KERNEL::norm<2>(tmp);
3401           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3402           *vals++=-tmp[1];
3403           *vals++=tmp[0];
3404         }
3405     }
3406   ret->setArray(array);
3407   ret->setMesh(this);
3408   ret->synchronizeTimeWithSupport();
3409   return ret.retn();
3410 }
3411
3412 /*!
3413  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3414  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3415  * and are normalized.
3416  * <br> \a this can be either 
3417  * - a  2D mesh in 2D or 3D space or 
3418  * - an 1D mesh in 2D space.
3419  * 
3420  * This method avoids building explicitly a part of \a this mesh to perform the work.
3421  *  \param [in] begin - an array of cell ids of interest.
3422  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3423  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3424  *          cells and one time. The caller is to delete this field using decrRef() as
3425  *          it is no more needed.
3426  *  \throw If the nodal connectivity of cells is not defined.
3427  *  \throw If the coordinates array is not set.
3428  *  \throw If the mesh dimension is not set.
3429  *  \throw If the mesh and space dimension is not as specified above.
3430  *  \sa buildOrthogonalField()
3431  *
3432  *  \if ENABLE_EXAMPLES
3433  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3434  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3435  *  \endif
3436  */
3437 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3438 {
3439   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3440     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3441   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3442   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3443   std::size_t nbelems=std::distance(begin,end);
3444   int nbComp=getMeshDimension()+1;
3445   array->alloc((int)nbelems,nbComp);
3446   double *vals=array->getPointer();
3447   const int *connI=_nodal_connec_index->getConstPointer();
3448   const int *conn=_nodal_connec->getConstPointer();
3449   const double *coords=_coords->getConstPointer();
3450   if(getMeshDimension()==2)
3451     {
3452       if(getSpaceDimension()==3)
3453         {
3454           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3455           const double *locPtr=loc->getConstPointer();
3456           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3457             {
3458               int offset=connI[*i];
3459               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3460               double n=INTERP_KERNEL::norm<3>(vals);
3461               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3462             }
3463         }
3464       else
3465         {
3466           for(std::size_t i=0;i<nbelems;i++)
3467             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3468         }
3469     }
3470   else//meshdimension==1
3471     {
3472       double tmp[2];
3473       for(const int *i=begin;i!=end;i++)
3474         {
3475           int offset=connI[*i];
3476           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3477           double n=INTERP_KERNEL::norm<2>(tmp);
3478           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3479           *vals++=-tmp[1];
3480           *vals++=tmp[0];
3481         }
3482     }
3483   ret->setArray(array);
3484   ret->setMesh(this);
3485   ret->synchronizeTimeWithSupport();
3486   return ret.retn();
3487 }
3488
3489 /*!
3490  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3491  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3492  * and are \b not normalized.
3493  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3494  *          cells and one time. The caller is to delete this field using decrRef() as
3495  *          it is no more needed.
3496  *  \throw If the nodal connectivity of cells is not defined.
3497  *  \throw If the coordinates array is not set.
3498  *  \throw If \a this->getMeshDimension() != 1.
3499  *  \throw If \a this mesh includes cells of type other than SEG2.
3500  */
3501 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3502 {
3503   if(getMeshDimension()!=1)
3504     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3505   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3506     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3507   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3508   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3509   int nbOfCells=getNumberOfCells();
3510   int spaceDim=getSpaceDimension();
3511   array->alloc(nbOfCells,spaceDim);
3512   double *pt=array->getPointer();
3513   const double *coo=getCoords()->getConstPointer();
3514   std::vector<int> conn;
3515   conn.reserve(2);
3516   for(int i=0;i<nbOfCells;i++)
3517     {
3518       conn.resize(0);
3519       getNodeIdsOfCell(i,conn);
3520       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3521     }
3522   ret->setArray(array);
3523   ret->setMesh(this);
3524   ret->synchronizeTimeWithSupport();
3525   return ret.retn();
3526 }
3527
3528 /*!
3529  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3530  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3531  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3532  * from. If a result face is shared by two 3D cells, then the face in included twice in
3533  * the result mesh.
3534  *  \param [in] origin - 3 components of a point defining location of the plane.
3535  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3536  *         must be greater than 1e-6.
3537  *  \param [in] eps - half-thickness of the plane.
3538  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3539  *         producing correspondent 2D cells. The caller is to delete this array
3540  *         using decrRef() as it is no more needed.
3541  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3542  *         not share the node coordinates array with \a this mesh. The caller is to
3543  *         delete this mesh using decrRef() as it is no more needed.  
3544  *  \throw If the coordinates array is not set.
3545  *  \throw If the nodal connectivity of cells is not defined.
3546  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3547  *  \throw If magnitude of \a vec is less than 1e-6.
3548  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3549  *  \throw If \a this includes quadratic cells.
3550  */
3551 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3552 {
3553   checkFullyDefined();
3554   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3555     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3556   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3557   if(candidates->empty())
3558     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3559   std::vector<int> nodes;
3560   DataArrayInt *cellIds1D=0;
3561   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3562   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3563   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3564   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3565   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3566   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3567   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3568   revDesc2=0; revDescIndx2=0;
3569   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3570   revDesc1=0; revDescIndx1=0;
3571   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3572   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3573   //
3574   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3575   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3576     cut3DCurve[*it]=-1;
3577   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3578   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3579   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3580                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3581                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3582   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3583   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3584   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3585   if(cellIds2->empty())
3586     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3587   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3588   ret->setCoords(mDesc1->getCoords());
3589   ret->setConnectivity(conn,connI,true);
3590   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3591   return ret.retn();
3592 }
3593
3594 /*!
3595  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3596 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
3597 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3598 the result mesh.
3599  *  \param [in] origin - 3 components of a point defining location of the plane.
3600  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3601  *         must be greater than 1e-6.
3602  *  \param [in] eps - half-thickness of the plane.
3603  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3604  *         producing correspondent segments. The caller is to delete this array
3605  *         using decrRef() as it is no more needed.
3606  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3607  *         mesh in 3D space. This mesh does not share the node coordinates array with
3608  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3609  *         no more needed. 
3610  *  \throw If the coordinates array is not set.
3611  *  \throw If the nodal connectivity of cells is not defined.
3612  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3613  *  \throw If magnitude of \a vec is less than 1e-6.
3614  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3615  *  \throw If \a this includes quadratic cells.
3616  */
3617 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3618 {
3619   checkFullyDefined();
3620   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3621     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3622   MCAuto<DataArrayInt> candidates(getCellIdsCrossingPlane(origin,vec,eps));
3623   if(candidates->empty())
3624     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3625   std::vector<int> nodes;
3626   DataArrayInt *cellIds1D(0);
3627   MCAuto<MEDCouplingUMesh> subMesh(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3628   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3629   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
3630   MCAuto<MEDCouplingUMesh> mDesc1(subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3631   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3632   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3633   //
3634   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3635   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3636     cut3DCurve[*it]=-1;
3637   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3638   int ncellsSub=subMesh->getNumberOfCells();
3639   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3640   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3641                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3642                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3643   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3644   conn->alloc(0,1);
3645   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3646   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3647   for(int i=0;i<ncellsSub;i++)
3648     {
3649       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3650         {
3651           if(cut3DSurf[i].first!=-2)
3652             {
3653               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3654               connI->pushBackSilent(conn->getNumberOfTuples());
3655               cellIds2->pushBackSilent(i);
3656             }
3657           else
3658             {
3659               int cellId3DSurf=cut3DSurf[i].second;
3660               int offset=nodalI[cellId3DSurf]+1;
3661               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3662               for(int j=0;j<nbOfEdges;j++)
3663                 {
3664                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3665                   connI->pushBackSilent(conn->getNumberOfTuples());
3666                   cellIds2->pushBackSilent(cellId3DSurf);
3667                 }
3668             }
3669         }
3670     }
3671   if(cellIds2->empty())
3672     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3673   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3674   ret->setCoords(mDesc1->getCoords());
3675   ret->setConnectivity(conn,connI,true);
3676   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3677   return ret.retn();
3678 }
3679
3680 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::clipSingle3DCellByPlane(const double origin[3], const double vec[3], double eps) const
3681 {
3682   checkFullyDefined();
3683   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3684     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3685   if(getNumberOfCells()!=1)
3686     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works only on mesh containing exactly one cell !");
3687   //
3688   std::vector<int> nodes;
3689   findNodesOnPlane(origin,vec,eps,nodes);
3690   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());
3691   MCAuto<MEDCouplingUMesh> mDesc2(buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2));//meshDim==2 spaceDim==3
3692   revDesc2=0; revDescIndx2=0;
3693   MCAuto<MEDCouplingUMesh> mDesc1(mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3694   revDesc1=0; revDescIndx1=0;
3695   DataArrayInt *cellIds1D(0);
3696   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3697   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3698   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3699   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3700     cut3DCurve[*it]=-1;
3701   bool sameNbNodes;
3702   {
3703     int oldNbNodes(mDesc1->getNumberOfNodes());
3704     mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3705     sameNbNodes=(mDesc1->getNumberOfNodes()==oldNbNodes);
3706   }
3707   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3708   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->begin(),mDesc2->getNodalConnectivityIndex()->begin(),
3709                               mDesc1->getNodalConnectivity()->begin(),mDesc1->getNodalConnectivityIndex()->begin(),
3710                               desc1->begin(),descIndx1->begin(),cut3DSurf);
3711   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New());
3712   connI->pushBackSilent(0); conn->alloc(0,1);
3713   {
3714     MCAuto<DataArrayInt> cellIds2(DataArrayInt::New()); cellIds2->alloc(0,1);
3715     assemblyForSplitFrom3DSurf(cut3DSurf,desc2->begin(),descIndx2->begin(),conn,connI,cellIds2);
3716     if(cellIds2->empty())
3717       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3718   }
3719   std::vector<std::vector<int> > res;
3720   buildSubCellsFromCut(cut3DSurf,desc2->begin(),descIndx2->begin(),mDesc1->getCoords()->begin(),eps,res);
3721   std::size_t sz(res.size());
3722   if(res.size()==mDesc1->getNumberOfCells() && sameNbNodes)
3723     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane : cell is not clipped !");
3724   for(std::size_t i=0;i<sz;i++)
3725     {
3726       conn->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
3727       conn->insertAtTheEnd(res[i].begin(),res[i].end());
3728       connI->pushBackSilent(conn->getNumberOfTuples());
3729     }
3730   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
3731   ret->setCoords(mDesc1->getCoords());
3732   ret->setConnectivity(conn,connI,true);
3733   int nbCellsRet(ret->getNumberOfCells());
3734   //
3735   MCAuto<DataArrayDouble> vec2(DataArrayDouble::New()); vec2->alloc(1,3); std::copy(vec,vec+3,vec2->getPointer());
3736   MCAuto<MEDCouplingFieldDouble> ortho(ret->buildOrthogonalField());
3737   MCAuto<DataArrayDouble> ortho2(ortho->getArray()->selectByTupleIdSafeSlice(0,1,1));
3738   MCAuto<DataArrayDouble> dott(DataArrayDouble::Dot(ortho2,vec2));
3739   MCAuto<DataArrayDouble> ccm(ret->computeCellCenterOfMass());
3740   MCAuto<DataArrayDouble> occm;
3741   {
3742     MCAuto<DataArrayDouble> pt(DataArrayDouble::New()); pt->alloc(1,3); std::copy(origin,origin+3,pt->getPointer());
3743     occm=DataArrayDouble::Substract(ccm,pt);
3744   }
3745   vec2=DataArrayDouble::New(); vec2->alloc(nbCellsRet,3);
3746   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);
3747   MCAuto<DataArrayDouble> dott2(DataArrayDouble::Dot(occm,vec2));
3748   //
3749   const int *cPtr(ret->getNodalConnectivity()->begin()),*ciPtr(ret->getNodalConnectivityIndex()->begin());
3750   MCAuto<MEDCouplingUMesh> ret2(MEDCouplingUMesh::New("Clip3D",3));
3751   ret2->setCoords(mDesc1->getCoords());
3752   MCAuto<DataArrayInt> conn2(DataArrayInt::New()),conn2I(DataArrayInt::New());
3753   conn2I->pushBackSilent(0); conn2->alloc(0,1);
3754   std::vector<int> cell0(1,(int)INTERP_KERNEL::NORM_POLYHED);
3755   std::vector<int> cell1(1,(int)INTERP_KERNEL::NORM_POLYHED);
3756   if(dott->getIJ(0,0)>0)
3757     {
3758       cell0.insert(cell0.end(),cPtr+1,cPtr+ciPtr[1]);
3759       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell1,cell1.end()));
3760     }
3761   else
3762     {
3763       cell1.insert(cell1.end(),cPtr+1,cPtr+ciPtr[1]);
3764       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell0,cell0.end()));
3765     }
3766   for(int i=1;i<nbCellsRet;i++)
3767     {
3768       if(dott2->getIJ(i,0)<0)
3769         {
3770           if(ciPtr[i+1]-ciPtr[i]>=4)
3771             {
3772               cell0.push_back(-1);
3773               cell0.insert(cell0.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3774             }
3775         }
3776       else
3777         {
3778           if(ciPtr[i+1]-ciPtr[i]>=4)
3779             {
3780               cell1.push_back(-1);
3781               cell1.insert(cell1.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3782             }
3783         }
3784     }
3785   conn2->insertAtTheEnd(cell0.begin(),cell0.end());
3786   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3787   conn2->insertAtTheEnd(cell1.begin(),cell1.end());
3788   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3789   ret2->setConnectivity(conn2,conn2I,true);
3790   ret2->checkConsistencyLight();
3791   ret2->orientCorrectlyPolyhedrons();
3792   return ret2;
3793 }
3794
3795 /*!
3796  * Finds cells whose bounding boxes intersect a given plane.
3797  *  \param [in] origin - 3 components of a point defining location of the plane.
3798  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3799  *         must be greater than 1e-6.
3800  *  \param [in] eps - half-thickness of the plane.
3801  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3802  *         cells. The caller is to delete this array using decrRef() as it is no more
3803  *         needed.
3804  *  \throw If the coordinates array is not set.
3805  *  \throw If the nodal connectivity of cells is not defined.
3806  *  \throw If \a this->getSpaceDimension() != 3.
3807  *  \throw If magnitude of \a vec is less than 1e-6.
3808  *  \sa buildSlice3D()
3809  */
3810 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3811 {
3812   checkFullyDefined();
3813   if(getSpaceDimension()!=3)
3814     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3815   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3816   if(normm<1e-6)
3817     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3818   double vec2[3];
3819   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3820   double angle=acos(vec[2]/normm);
3821   MCAuto<DataArrayInt> cellIds;
3822   double bbox[6];
3823   if(angle>eps)
3824     {
3825       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3826       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3827       if(normm2/normm>1e-6)
3828         DataArrayDouble::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer(),coo->getPointer());
3829       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3830       mw->setCoords(coo);
3831       mw->getBoundingBox(bbox);
3832       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3833       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3834     }
3835   else
3836     {
3837       getBoundingBox(bbox);
3838       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3839       cellIds=getCellsInBoundingBox(bbox,eps);
3840     }
3841   return cellIds.retn();
3842 }
3843
3844 /*!
3845  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3846  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3847  * No consideration of coordinate is done by this method.
3848  * 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)
3849  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
3850  */
3851 bool MEDCouplingUMesh::isContiguous1D() const
3852 {
3853   if(getMeshDimension()!=1)
3854     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3855   int nbCells=getNumberOfCells();
3856   if(nbCells<1)
3857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3858   const int *connI(_nodal_connec_index->begin()),*conn(_nodal_connec->begin());
3859   int ref=conn[connI[0]+2];
3860   for(int i=1;i<nbCells;i++)
3861     {
3862       if(conn[connI[i]+1]!=ref)
3863         return false;
3864       ref=conn[connI[i]+2];
3865     }
3866   return true;
3867 }
3868
3869 /*!
3870  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3871  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3872  * \param pt reference point of the line
3873  * \param v normalized director vector of the line
3874  * \param eps max precision before throwing an exception
3875  * \param res output of size this->getNumberOfCells
3876  */
3877 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3878 {
3879   if(getMeshDimension()!=1)
3880     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3881   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3882     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3883   if(getSpaceDimension()!=3)
3884     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3885   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3886   const double *fPtr=f->getArray()->getConstPointer();
3887   double tmp[3];
3888   for(std::size_t i=0;i<getNumberOfCells();i++)
3889     {
3890       const double *tmp1=fPtr+3*i;
3891       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3892       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3893       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3894       double n1=INTERP_KERNEL::norm<3>(tmp);
3895       n1/=INTERP_KERNEL::norm<3>(tmp1);
3896       if(n1>eps)
3897         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3898     }
3899   const double *coo=getCoords()->getConstPointer();
3900   for(int i=0;i<getNumberOfNodes();i++)
3901     {
3902       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3903       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3904       res[i]=std::accumulate(tmp,tmp+3,0.);
3905     }
3906 }
3907
3908 /*!
3909  * 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. 
3910  * \a this is expected to be a mesh so that its space dimension is equal to its
3911  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3912  * 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).
3913  *
3914  * 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
3915  * 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).
3916  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3917  *
3918  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3919  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3920  *
3921  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3922  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3923  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3924  * \return the positive value of the distance.
3925  * \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
3926  * dimension - 1.
3927  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3928  */
3929 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3930 {
3931   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3932   if(meshDim!=spaceDim-1)
3933     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3934   if(meshDim!=2 && meshDim!=1)
3935     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3936   checkFullyDefined();
3937   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3938     { 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()); }
3939   DataArrayInt *ret1=0;
3940   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3941   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3942   MCAuto<DataArrayInt> ret1Safe(ret1);
3943   cellId=*ret1Safe->begin();
3944   return *ret0->begin();
3945 }
3946
3947 /*!
3948  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3949  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3950  * 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
3951  * 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).
3952  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3953  * 
3954  * \a this is expected to be a mesh so that its space dimension is equal to its
3955  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3956  * 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).
3957  *
3958  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3959  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3960  *
3961  * \param [in] pts the list of points in which each tuple represents a point
3962  * \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.
3963  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3964  * \throw if number of components of \a pts is not equal to the space dimension.
3965  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3966  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3967  */
3968 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3969 {
3970   if(!pts)
3971     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3972   pts->checkAllocated();
3973   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3974   if(meshDim!=spaceDim-1)
3975     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3976   if(meshDim!=2 && meshDim!=1)
3977     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3978   if((int)pts->getNumberOfComponents()!=spaceDim)
3979     {
3980       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3981       throw INTERP_KERNEL::Exception(oss.str());
3982     }
3983   checkFullyDefined();
3984   int nbCells=getNumberOfCells();
3985   if(nbCells==0)
3986     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3987   int nbOfPts=pts->getNumberOfTuples();
3988   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3989   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3990   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3991   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3992   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3993   const double *bbox(bboxArr->begin());
3994   switch(spaceDim)
3995   {
3996     case 3:
3997       {
3998         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3999         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4000           {
4001             double x=std::numeric_limits<double>::max();
4002             std::vector<int> elems;
4003             myTree.getMinDistanceOfMax(ptsPtr,x);
4004             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4005             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4006           }
4007         break;
4008       }
4009     case 2:
4010       {
4011         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4012         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4013           {
4014             double x=std::numeric_limits<double>::max();
4015             std::vector<int> elems;
4016             myTree.getMinDistanceOfMax(ptsPtr,x);
4017             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4018             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4019           }
4020         break;
4021       }
4022     default:
4023       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4024   }
4025   cellIds=ret1.retn();
4026   return ret0.retn();
4027 }
4028
4029 /// @cond INTERNAL
4030
4031 /// @endcond
4032
4033 /*!
4034  * Finds cells in contact with a ball (i.e. a point with precision). 
4035  * 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.
4036  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4037  *
4038  * \warning This method is suitable if the caller intends to evaluate only one
4039  *          point, for more points getCellsContainingPoints() is recommended as it is
4040  *          faster. 
4041  *  \param [in] pos - array of coordinates of the ball central point.
4042  *  \param [in] eps - ball radius.
4043  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4044  *         if there are no such cells.
4045  *  \throw If the coordinates array is not set.
4046  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4047  */
4048 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4049 {
4050   std::vector<int> elts;
4051   getCellsContainingPoint(pos,eps,elts);
4052   if(elts.empty())
4053     return -1;
4054   return elts.front();
4055 }
4056
4057 /*!
4058  * Finds cells in contact with a ball (i.e. a point with precision).
4059  * 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.
4060  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4061  * \warning This method is suitable if the caller intends to evaluate only one
4062  *          point, for more points getCellsContainingPoints() is recommended as it is
4063  *          faster. 
4064  *  \param [in] pos - array of coordinates of the ball central point.
4065  *  \param [in] eps - ball radius.
4066  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4067  *         before inserting ids.
4068  *  \throw If the coordinates array is not set.
4069  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4070  *
4071  *  \if ENABLE_EXAMPLES
4072  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4073  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4074  *  \endif
4075  */
4076 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4077 {
4078   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4079   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4080   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4081 }
4082
4083 /*!
4084  * Finds cells in contact with several balls (i.e. points with precision).
4085  * This method is an extension of getCellContainingPoint() and
4086  * getCellsContainingPoint() for the case of multiple points.
4087  * 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.
4088  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4089  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4090  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4091  *         this->getSpaceDimension() * \a nbOfPoints 
4092  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4093  *  \param [in] eps - radius of balls (i.e. the precision).
4094  *  \param [out] elts - vector returning ids of found cells.
4095  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4096  *         dividing cell ids in \a elts into groups each referring to one
4097  *         point. Its every element (except the last one) is an index pointing to the
4098  *         first id of a group of cells. For example cells in contact with the *i*-th
4099  *         point are described by following range of indices:
4100  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4101  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4102  *         Number of cells in contact with the *i*-th point is
4103  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4104  *  \throw If the coordinates array is not set.
4105  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4106  *
4107  *  \if ENABLE_EXAMPLES
4108  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4109  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4110  *  \endif
4111  */
4112 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4113                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4114 {
4115   int spaceDim=getSpaceDimension();
4116   int mDim=getMeshDimension();
4117   if(spaceDim==3)
4118     {
4119       if(mDim==3)
4120         {
4121           const double *coords=_coords->getConstPointer();
4122           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4123         }
4124       /*else if(mDim==2)
4125         {
4126
4127         }*/
4128       else
4129         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4130     }
4131   else if(spaceDim==2)
4132     {
4133       if(mDim==2)
4134         {
4135           const double *coords=_coords->getConstPointer();
4136           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4137         }
4138       else
4139         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4140     }
4141   else if(spaceDim==1)
4142     {
4143       if(mDim==1)
4144         {
4145           const double *coords=_coords->getConstPointer();
4146           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4147         }
4148       else
4149         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4150     }
4151   else
4152     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4153 }
4154
4155 /*!
4156  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4157  * least two its edges intersect each other anywhere except their extremities. An
4158  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4159  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4160  *         cleared before filling in.
4161  *  \param [in] eps - precision.
4162  *  \throw If \a this->getMeshDimension() != 2.
4163  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4164  */
4165 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4166 {
4167   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4168   if(getMeshDimension()!=2)
4169     throw INTERP_KERNEL::Exception(msg);
4170   int spaceDim=getSpaceDimension();
4171   if(spaceDim!=2 && spaceDim!=3)
4172     throw INTERP_KERNEL::Exception(msg);
4173   const int *conn=_nodal_connec->getConstPointer();
4174   const int *connI=_nodal_connec_index->getConstPointer();
4175   int nbOfCells=getNumberOfCells();
4176   std::vector<double> cell2DinS2;
4177   for(int i=0;i<nbOfCells;i++)
4178     {
4179       int offset=connI[i];
4180       int nbOfNodesForCell=connI[i+1]-offset-1;
4181       if(nbOfNodesForCell<=3)
4182         continue;
4183       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4184       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4185       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4186         cells.push_back(i);
4187       cell2DinS2.clear();
4188     }
4189 }
4190
4191 /*!
4192  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4193  *
4194  * 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.
4195  * 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.
4196  * 
4197  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4198  * This convex envelop is computed using Jarvis march algorithm.
4199  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4200  * 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)
4201  * 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.
4202  *
4203  * \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.
4204  * \sa MEDCouplingUMesh::colinearize2D
4205  */
4206 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4207 {
4208   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4209     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4210   checkFullyDefined();
4211   const double *coords=getCoords()->getConstPointer();
4212   int nbOfCells=getNumberOfCells();
4213   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4214   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4215   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4216   int *workIndexOut=nodalConnecIndexOut->getPointer();
4217   *workIndexOut=0;
4218   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4219   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4220   std::set<INTERP_KERNEL::NormalizedCellType> types;
4221   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4222   isChanged->alloc(0,1);
4223   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4224     {
4225       int pos=nodalConnecOut->getNumberOfTuples();
4226       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4227         isChanged->pushBackSilent(i);
4228       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4229       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4230     }
4231   if(isChanged->empty())
4232     return 0;
4233   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4234   _types=types;
4235   return isChanged.retn();
4236 }
4237
4238 /*!
4239  * This method is \b NOT const because it can modify \a this.
4240  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4241  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4242  * \param policy specifies the type of extrusion chosen:
4243  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4244  *   will be repeated to build each level
4245  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4246  *   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
4247  *   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
4248  *   arc.
4249  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4250  */
4251 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4252 {
4253   checkFullyDefined();
4254   mesh1D->checkFullyDefined();
4255   if(!mesh1D->isContiguous1D())
4256     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4257   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4258     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4259   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4260     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4261   if(mesh1D->getMeshDimension()!=1)
4262     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4263   bool isQuad=false;
4264   if(isPresenceOfQuadratic())
4265     {
4266       if(mesh1D->isFullyQuadratic())
4267         isQuad=true;
4268       else
4269         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4270     }
4271   int oldNbOfNodes(getNumberOfNodes());
4272   MCAuto<DataArrayDouble> newCoords;
4273   switch(policy)
4274   {
4275     case 0:
4276       {
4277         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4278         break;
4279       }
4280     case 1:
4281       {
4282         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4283         break;
4284       }
4285     default:
4286       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4287   }
4288   setCoords(newCoords);
4289   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4290   updateTime();
4291   return ret.retn();
4292 }
4293
4294
4295 /*!
4296  * Checks if \a this mesh is constituted by only quadratic cells.
4297  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4298  *  \throw If the coordinates array is not set.
4299  *  \throw If the nodal connectivity of cells is not defined.
4300  */
4301 bool MEDCouplingUMesh::isFullyQuadratic() const
4302 {
4303   checkFullyDefined();
4304   bool ret=true;
4305   int nbOfCells=getNumberOfCells();
4306   for(int i=0;i<nbOfCells && ret;i++)
4307     {
4308       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4309       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4310       ret=cm.isQuadratic();
4311     }
4312   return ret;
4313 }
4314
4315 /*!
4316  * Checks if \a this mesh includes any quadratic cell.
4317  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4318  *  \throw If the coordinates array is not set.
4319  *  \throw If the nodal connectivity of cells is not defined.
4320  */
4321 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4322 {
4323   checkFullyDefined();
4324   bool ret=false;
4325   int nbOfCells=getNumberOfCells();
4326   for(int i=0;i<nbOfCells && !ret;i++)
4327     {
4328       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4329       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4330       ret=cm.isQuadratic();
4331     }
4332   return ret;
4333 }
4334
4335 /*!
4336  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4337  * this mesh, it remains unchanged.
4338  *  \throw If the coordinates array is not set.
4339  *  \throw If the nodal connectivity of cells is not defined.
4340  */
4341 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4342 {
4343   checkFullyDefined();
4344   int nbOfCells(getNumberOfCells());
4345   int delta=0;
4346   const int *iciptr=_nodal_connec_index->begin();
4347   for(int i=0;i<nbOfCells;i++)
4348     {
4349       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4350       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4351       if(cm.isQuadratic())
4352         {
4353           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4354           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4355           if(!cml.isDynamic())
4356             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4357           else
4358             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4359         }
4360     }
4361   if(delta==0)
4362     return ;
4363   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4364   const int *icptr(_nodal_connec->begin());
4365   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
4366   newConnI->alloc(nbOfCells+1,1);
4367   int *ocptr(newConn->getPointer()),*ociptr(newConnI->getPointer());
4368   *ociptr=0;
4369   _types.clear();
4370   for(int i=0;i<nbOfCells;i++,ociptr++)
4371     {
4372       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4373       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4374       if(!cm.isQuadratic())
4375         {
4376           _types.insert(type);
4377           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4378           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4379         }
4380       else
4381         {
4382           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4383           _types.insert(typel);
4384           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4385           int newNbOfNodes=cml.getNumberOfNodes();
4386           if(cml.isDynamic())
4387             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4388           *ocptr++=(int)typel;
4389           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4390           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4391         }
4392     }
4393   setConnectivity(newConn,newConnI,false);
4394 }
4395
4396 /*!
4397  * This method converts all linear cell in \a this to quadratic one.
4398  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4399  * 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)
4400  * 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.
4401  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4402  * end of the existing coordinates.
4403  * 
4404  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4405  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4406  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4407  * 
4408  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4409  *
4410  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4411  */
4412 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4413 {
4414   DataArrayInt *conn=0,*connI=0;
4415   DataArrayDouble *coords=0;
4416   std::set<INTERP_KERNEL::NormalizedCellType> types;
4417   checkFullyDefined();
4418   MCAuto<DataArrayInt> ret,connSafe,connISafe;
4419   MCAuto<DataArrayDouble> coordsSafe;
4420   int meshDim=getMeshDimension();
4421   switch(conversionType)
4422   {
4423     case 0:
4424       switch(meshDim)
4425       {
4426         case 1:
4427           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4428           connSafe=conn; connISafe=connI; coordsSafe=coords;
4429           break;
4430         case 2:
4431           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4432           connSafe=conn; connISafe=connI; coordsSafe=coords;
4433           break;
4434         case 3:
4435           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4436           connSafe=conn; connISafe=connI; coordsSafe=coords;
4437           break;
4438         default:
4439           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4440       }
4441       break;
4442         case 1:
4443           {
4444             switch(meshDim)
4445             {
4446               case 1:
4447                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4448                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4449                 break;
4450               case 2:
4451                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4452                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4453                 break;
4454               case 3:
4455                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4456                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4457                 break;
4458               default:
4459                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4460             }
4461             break;
4462           }
4463         default:
4464           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4465   }
4466   setConnectivity(connSafe,connISafe,false);
4467   _types=types;
4468   setCoords(coordsSafe);
4469   return ret.retn();
4470 }
4471
4472 /*!
4473  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
4474  * so that the number of cells remains the same. Quadratic faces are converted to
4475  * polygons. This method works only for 2D meshes in
4476  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
4477  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
4478  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4479  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
4480  *         a polylinized edge constituting the input polygon.
4481  *  \throw If the coordinates array is not set.
4482  *  \throw If the nodal connectivity of cells is not defined.
4483  *  \throw If \a this->getMeshDimension() != 2.
4484  *  \throw If \a this->getSpaceDimension() != 2.
4485  */
4486 void MEDCouplingUMesh::tessellate2D(double eps)
4487 {
4488   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
4489   if(spaceDim!=2)
4490     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
4491   switch(meshDim)
4492     {
4493     case 1:
4494       return tessellate2DCurveInternal(eps);
4495     case 2:
4496       return tessellate2DInternal(eps);
4497     default:
4498       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
4499     }
4500 }
4501 /*!
4502  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
4503  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4504  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
4505  *         a sub-divided edge.
4506  *  \throw If the coordinates array is not set.
4507  *  \throw If the nodal connectivity of cells is not defined.
4508  *  \throw If \a this->getMeshDimension() != 1.
4509  *  \throw If \a this->getSpaceDimension() != 2.
4510  */
4511
4512 #if 0
4513 /*!
4514  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
4515  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
4516  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
4517  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
4518  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
4519  * This method can be seen as the opposite method of colinearize2D.
4520  * 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
4521  * to avoid to modify the numbering of existing nodes.
4522  *
4523  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
4524  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
4525  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
4526  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
4527  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
4528  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
4529  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
4530  *
4531  * \sa buildDescendingConnectivity2
4532  */
4533 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
4534                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
4535 {
4536   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
4537     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
4538   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
4539   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
4540     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
4541   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
4542     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
4543   //DataArrayInt *out0(0),*outi0(0);
4544   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
4545   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
4546   //out0s=out0s->buildUnique(); out0s->sort(true);
4547 }
4548 #endif
4549
4550
4551 /*!
4552  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
4553  * In addition, returns an array mapping new cells to old ones. <br>
4554  * This method typically increases the number of cells in \a this mesh
4555  * but the number of nodes remains \b unchanged.
4556  * That's why the 3D splitting policies
4557  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
4558  *  \param [in] policy - specifies a pattern used for splitting.
4559  * The semantic of \a policy is:
4560  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
4561  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
4562  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4563  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4564  *
4565  *
4566  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
4567  *          an id of old cell producing it. The caller is to delete this array using
4568  *         decrRef() as it is no more needed.
4569  *
4570  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
4571  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
4572  *          and \a this->getMeshDimension() != 3. 
4573  *  \throw If \a policy is not one of the four discussed above.
4574  *  \throw If the nodal connectivity of cells is not defined.
4575  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
4576  */
4577 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
4578 {
4579   switch(policy)
4580   {
4581     case 0:
4582       return simplexizePol0();
4583     case 1:
4584       return simplexizePol1();
4585     case (int) INTERP_KERNEL::PLANAR_FACE_5:
4586         return simplexizePlanarFace5();
4587     case (int) INTERP_KERNEL::PLANAR_FACE_6:
4588         return simplexizePlanarFace6();
4589     default:
4590       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)");
4591   }
4592 }
4593
4594 /*!
4595  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
4596  * - 1D: INTERP_KERNEL::NORM_SEG2
4597  * - 2D: INTERP_KERNEL::NORM_TRI3
4598  * - 3D: INTERP_KERNEL::NORM_TETRA4.
4599  *
4600  * This method is useful for users that need to use P1 field services as
4601  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
4602  * All these methods need mesh support containing only simplex cells.
4603  *  \return bool - \c true if there are only simplex cells in \a this mesh.
4604  *  \throw If the coordinates array is not set.
4605  *  \throw If the nodal connectivity of cells is not defined.
4606  *  \throw If \a this->getMeshDimension() < 1.
4607  */
4608 bool MEDCouplingUMesh::areOnlySimplexCells() const
4609 {
4610   checkFullyDefined();
4611   int mdim=getMeshDimension();
4612   if(mdim<1 || mdim>3)
4613     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
4614   int nbCells=getNumberOfCells();
4615   const int *conn=_nodal_connec->begin();
4616   const int *connI=_nodal_connec_index->begin();
4617   for(int i=0;i<nbCells;i++)
4618     {
4619       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4620       if(!cm.isSimplex())
4621         return false;
4622     }
4623   return true;
4624 }
4625
4626
4627
4628 /*!
4629  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
4630  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
4631  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
4632  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
4633  * so it can be useful to call mergeNodes() before calling this method.
4634  *  \throw If \a this->getMeshDimension() <= 1.
4635  *  \throw If the coordinates array is not set.
4636  *  \throw If the nodal connectivity of cells is not defined.
4637  */
4638 void MEDCouplingUMesh::convertDegeneratedCells()
4639 {
4640   checkFullyDefined();
4641   if(getMeshDimension()<=1)
4642     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4643   int nbOfCells=getNumberOfCells();
4644   if(nbOfCells<1)
4645     return ;
4646   int initMeshLgth=getNodalConnectivityArrayLen();
4647   int *conn=_nodal_connec->getPointer();
4648   int *index=_nodal_connec_index->getPointer();
4649   int posOfCurCell=0;
4650   int newPos=0;
4651   int lgthOfCurCell;
4652   for(int i=0;i<nbOfCells;i++)
4653     {
4654       lgthOfCurCell=index[i+1]-posOfCurCell;
4655       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4656       int newLgth;
4657       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4658                                                                                                      conn+newPos+1,newLgth);
4659       conn[newPos]=newType;
4660       newPos+=newLgth+1;
4661       posOfCurCell=index[i+1];
4662       index[i+1]=newPos;
4663     }
4664   if(newPos!=initMeshLgth)
4665     _nodal_connec->reAlloc(newPos);
4666   computeTypes();
4667 }
4668
4669 /*!
4670  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
4671  * A cell is considered to be oriented correctly if an angle between its
4672  * normal vector and a given vector is less than \c PI / \c 2.
4673  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4674  *         cells. 
4675  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4676  *         checked.
4677  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4678  *         is not cleared before filling in.
4679  *  \throw If \a this->getMeshDimension() != 2.
4680  *  \throw If \a this->getSpaceDimension() != 3.
4681  *
4682  *  \if ENABLE_EXAMPLES
4683  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4684  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4685  *  \endif
4686  */
4687 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
4688 {
4689   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4690     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4691   int nbOfCells=getNumberOfCells();
4692   const int *conn=_nodal_connec->begin();
4693   const int *connI=_nodal_connec_index->begin();
4694   const double *coordsPtr=_coords->begin();
4695   for(int i=0;i<nbOfCells;i++)
4696     {
4697       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4698       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4699         {
4700           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4701           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4702             cells.push_back(i);
4703         }
4704     }
4705 }
4706
4707 /*!
4708  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
4709  * considered to be oriented correctly if an angle between its normal vector and a
4710  * given vector is less than \c PI / \c 2. 
4711  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4712  *         cells. 
4713  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4714  *         checked.
4715  *  \throw If \a this->getMeshDimension() != 2.
4716  *  \throw If \a this->getSpaceDimension() != 3.
4717  *
4718  *  \if ENABLE_EXAMPLES
4719  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4720  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4721  *  \endif
4722  *
4723  *  \sa changeOrientationOfCells
4724  */
4725 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
4726 {
4727   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4728     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
4729   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4730   const int *connI(_nodal_connec_index->begin());
4731   const double *coordsPtr(_coords->begin());
4732   bool isModified(false);
4733   for(int i=0;i<nbOfCells;i++)
4734     {
4735       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4736       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4737         {
4738           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4739           bool isQuadratic(cm.isQuadratic());
4740           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4741             {
4742               isModified=true;
4743               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4744             }
4745         }
4746     }
4747   if(isModified)
4748     _nodal_connec->declareAsNew();
4749   updateTime();
4750 }
4751
4752 /*!
4753  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
4754  *
4755  * \sa orientCorrectly2DCells
4756  */
4757 void MEDCouplingUMesh::changeOrientationOfCells()
4758 {
4759   int mdim(getMeshDimension());
4760   if(mdim!=2 && mdim!=1)
4761     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
4762   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4763   const int *connI(_nodal_connec_index->begin());
4764   if(mdim==2)
4765     {//2D
4766       for(int i=0;i<nbOfCells;i++)
4767         {
4768           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4769           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4770           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4771         }
4772     }
4773   else
4774     {//1D
4775       for(int i=0;i<nbOfCells;i++)
4776         {
4777           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4778           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4779           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4780         }
4781     }
4782 }
4783
4784 /*!
4785  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
4786  * oriented facets. The normal vector of the facet should point out of the cell.
4787  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4788  *         is not cleared before filling in.
4789  *  \throw If \a this->getMeshDimension() != 3.
4790  *  \throw If \a this->getSpaceDimension() != 3.
4791  *  \throw If the coordinates array is not set.
4792  *  \throw If the nodal connectivity of cells is not defined.
4793  *
4794  *  \if ENABLE_EXAMPLES
4795  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4796  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4797  *  \endif
4798  */
4799 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
4800 {
4801   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4802     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
4803   int nbOfCells=getNumberOfCells();
4804   const int *conn=_nodal_connec->begin();
4805   const int *connI=_nodal_connec_index->begin();
4806   const double *coordsPtr=_coords->begin();
4807   for(int i=0;i<nbOfCells;i++)
4808     {
4809       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4810       if(type==INTERP_KERNEL::NORM_POLYHED)
4811         {
4812           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4813             cells.push_back(i);
4814         }
4815     }
4816 }
4817
4818 /*!
4819  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
4820  * out of the cell. 
4821  *  \throw If \a this->getMeshDimension() != 3.
4822  *  \throw If \a this->getSpaceDimension() != 3.
4823  *  \throw If the coordinates array is not set.
4824  *  \throw If the nodal connectivity of cells is not defined.
4825  *  \throw If the reparation fails.
4826  *
4827  *  \if ENABLE_EXAMPLES
4828  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4829  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4830  *  \endif
4831  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4832  */
4833 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
4834 {
4835   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4836     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
4837   int nbOfCells=getNumberOfCells();
4838   int *conn=_nodal_connec->getPointer();
4839   const int *connI=_nodal_connec_index->begin();
4840   const double *coordsPtr=_coords->begin();
4841   for(int i=0;i<nbOfCells;i++)
4842     {
4843       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4844       if(type==INTERP_KERNEL::NORM_POLYHED)
4845         {
4846           try
4847           {
4848               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4849                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4850           }
4851           catch(INTERP_KERNEL::Exception& e)
4852           {
4853               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
4854               throw INTERP_KERNEL::Exception(oss.str());
4855           }
4856         }
4857     }
4858   updateTime();
4859 }
4860
4861 /*!
4862  * This method invert orientation of all cells in \a this. 
4863  * After calling this method the absolute value of measure of cells in \a this are the same than before calling.
4864  * This method only operates on the connectivity so coordinates are not touched at all.
4865  */
4866 void MEDCouplingUMesh::invertOrientationOfAllCells()
4867 {
4868   checkConnectivityFullyDefined();
4869   std::set<INTERP_KERNEL::NormalizedCellType> gts(getAllGeoTypes());
4870   int *conn(_nodal_connec->getPointer());
4871   const int *conni(_nodal_connec_index->begin());
4872   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator gt=gts.begin();gt!=gts.end();gt++)
4873     {
4874       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::OrientationInverter> oi(INTERP_KERNEL::OrientationInverter::BuildInstanceFrom(*gt));
4875       MCAuto<DataArrayInt> cwt(giveCellsWithType(*gt));
4876       for(const int *it=cwt->begin();it!=cwt->end();it++)
4877         oi->operate(conn+conni[*it]+1,conn+conni[*it+1]);
4878     }
4879   updateTime();
4880 }
4881
4882 /*!
4883  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
4884  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
4885  * according to which the first facet of the cell should be oriented to have the normal vector
4886  * pointing out of cell.
4887  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
4888  *         cells. The caller is to delete this array using decrRef() as it is no more
4889  *         needed. 
4890  *  \throw If \a this->getMeshDimension() != 3.
4891  *  \throw If \a this->getSpaceDimension() != 3.
4892  *  \throw If the coordinates array is not set.
4893  *  \throw If the nodal connectivity of cells is not defined.
4894  *
4895  *  \if ENABLE_EXAMPLES
4896  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
4897  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
4898  *  \endif
4899  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4900  */
4901 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
4902 {
4903   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
4904   if(getMeshDimension()!=3)
4905     throw INTERP_KERNEL::Exception(msg);
4906   int spaceDim=getSpaceDimension();
4907   if(spaceDim!=3)
4908     throw INTERP_KERNEL::Exception(msg);
4909   //
4910   int nbOfCells=getNumberOfCells();
4911   int *conn=_nodal_connec->getPointer();
4912   const int *connI=_nodal_connec_index->begin();
4913   const double *coo=getCoords()->begin();
4914   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
4915   for(int i=0;i<nbOfCells;i++)
4916     {
4917       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4918       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
4919         {
4920           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
4921             {
4922               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4923               cells->pushBackSilent(i);
4924             }
4925         }
4926     }
4927   return cells.retn();
4928 }
4929
4930 /*!
4931  * This method is a faster method to correct orientation of all 3D cells in \a this.
4932  * 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.
4933  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
4934  * 
4935  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
4936  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
4937  */
4938 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
4939 {
4940   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4941     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
4942   int nbOfCells=getNumberOfCells();
4943   int *conn=_nodal_connec->getPointer();
4944   const int *connI=_nodal_connec_index->begin();
4945   const double *coordsPtr=_coords->begin();
4946   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4947   for(int i=0;i<nbOfCells;i++)
4948     {
4949       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4950       switch(type)
4951       {
4952         case INTERP_KERNEL::NORM_TETRA4:
4953           {
4954             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4955               {
4956                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
4957                 ret->pushBackSilent(i);
4958               }
4959             break;
4960           }
4961         case INTERP_KERNEL::NORM_PYRA5:
4962           {
4963             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4964               {
4965                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
4966                 ret->pushBackSilent(i);
4967               }
4968             break;
4969           }
4970         case INTERP_KERNEL::NORM_PENTA6:
4971         case INTERP_KERNEL::NORM_HEXA8:
4972         case INTERP_KERNEL::NORM_HEXGP12:
4973           {
4974             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4975               {
4976                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4977                 ret->pushBackSilent(i);
4978               }
4979             break;
4980           }
4981         case INTERP_KERNEL::NORM_POLYHED:
4982           {
4983             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4984               {
4985                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4986                 ret->pushBackSilent(i);
4987               }
4988             break;
4989           }
4990         default:
4991           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 !");
4992       }
4993     }
4994   updateTime();
4995   return ret.retn();
4996 }
4997
4998 /*!
4999  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5000  * If it is not the case an exception will be thrown.
5001  * This method is fast because the first cell of \a this is used to compute the plane.
5002  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5003  * \param pos output of size at least 3 used to store a point owned of searched plane.
5004  */
5005 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5006 {
5007   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5008     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5009   const int *conn=_nodal_connec->begin();
5010   const int *connI=_nodal_connec_index->begin();
5011   const double *coordsPtr=_coords->begin();
5012   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5013   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5014 }
5015
5016 /*!
5017  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5018  * cells. Currently cells of the following types are treated:
5019  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5020  * For a cell of other type an exception is thrown.
5021  * Space dimension of a 2D mesh can be either 2 or 3.
5022  * The Edge Ratio of a cell \f$t\f$ is: 
5023  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5024  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5025  *  the smallest edge lengths of \f$t\f$.
5026  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5027  *          cells and one time, lying on \a this mesh. The caller is to delete this
5028  *          field using decrRef() as it is no more needed. 
5029  *  \throw If the coordinates array is not set.
5030  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5031  *  \throw If the connectivity data array has more than one component.
5032  *  \throw If the connectivity data array has a named component.
5033  *  \throw If the connectivity index data array has more than one component.
5034  *  \throw If the connectivity index data array has a named component.
5035  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5036  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5037  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5038  */
5039 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
5040 {
5041   checkConsistencyLight();
5042   int spaceDim=getSpaceDimension();
5043   int meshDim=getMeshDimension();
5044   if(spaceDim!=2 && spaceDim!=3)
5045     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5046   if(meshDim!=2 && meshDim!=3)
5047     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5048   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5049   ret->setMesh(this);
5050   int nbOfCells=getNumberOfCells();
5051   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5052   arr->alloc(nbOfCells,1);
5053   double *pt=arr->getPointer();
5054   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5055   const int *conn=_nodal_connec->begin();
5056   const int *connI=_nodal_connec_index->begin();
5057   const double *coo=_coords->begin();
5058   double tmp[12];
5059   for(int i=0;i<nbOfCells;i++,pt++)
5060     {
5061       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5062       switch(t)
5063       {
5064         case INTERP_KERNEL::NORM_TRI3:
5065           {
5066             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5067             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5068             break;
5069           }
5070         case INTERP_KERNEL::NORM_QUAD4:
5071           {
5072             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5073             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5074             break;
5075           }
5076         case INTERP_KERNEL::NORM_TETRA4:
5077           {
5078             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5079             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5080             break;
5081           }
5082         default:
5083           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5084       }
5085       conn+=connI[i+1]-connI[i];
5086     }
5087   ret->setName("EdgeRatio");
5088   ret->synchronizeTimeWithSupport();
5089   return ret.retn();
5090 }
5091
5092 /*!
5093  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5094  * cells. Currently cells of the following types are treated:
5095  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5096  * For a cell of other type an exception is thrown.
5097  * Space dimension of a 2D mesh can be either 2 or 3.
5098  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5099  *          cells and one time, lying on \a this mesh. The caller is to delete this
5100  *          field using decrRef() as it is no more needed. 
5101  *  \throw If the coordinates array is not set.
5102  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5103  *  \throw If the connectivity data array has more than one component.
5104  *  \throw If the connectivity data array has a named component.
5105  *  \throw If the connectivity index data array has more than one component.
5106  *  \throw If the connectivity index data array has a named component.
5107  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5108  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5109  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5110  */
5111 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
5112 {
5113   checkConsistencyLight();
5114   int spaceDim=getSpaceDimension();
5115   int meshDim=getMeshDimension();
5116   if(spaceDim!=2 && spaceDim!=3)
5117     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5118   if(meshDim!=2 && meshDim!=3)
5119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5120   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5121   ret->setMesh(this);
5122   int nbOfCells=getNumberOfCells();
5123   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5124   arr->alloc(nbOfCells,1);
5125   double *pt=arr->getPointer();
5126   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5127   const int *conn=_nodal_connec->begin();
5128   const int *connI=_nodal_connec_index->begin();
5129   const double *coo=_coords->begin();
5130   double tmp[12];
5131   for(int i=0;i<nbOfCells;i++,pt++)
5132     {
5133       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5134       switch(t)
5135       {
5136         case INTERP_KERNEL::NORM_TRI3:
5137           {
5138             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5139             *pt=INTERP_KERNEL::triAspectRatio(tmp);
5140             break;
5141           }
5142         case INTERP_KERNEL::NORM_QUAD4:
5143           {
5144             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5145             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5146             break;
5147           }
5148         case INTERP_KERNEL::NORM_TETRA4:
5149           {
5150             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5151             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5152             break;
5153           }
5154         default:
5155           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5156       }
5157       conn+=connI[i+1]-connI[i];
5158     }
5159   ret->setName("AspectRatio");
5160   ret->synchronizeTimeWithSupport();
5161   return ret.retn();
5162 }
5163
5164 /*!
5165  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
5166  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
5167  * in 3D space. Currently only cells of the following types are
5168  * treated: INTERP_KERNEL::NORM_QUAD4.
5169  * For a cell of other type an exception is thrown.
5170  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
5171  * Defining
5172  * \f$t=\vec{da}\times\vec{ab}\f$,
5173  * \f$u=\vec{ab}\times\vec{bc}\f$
5174  * \f$v=\vec{bc}\times\vec{cd}\f$
5175  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
5176  *  \f[
5177  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
5178  *  \f]
5179  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5180  *          cells and one time, lying on \a this mesh. The caller is to delete this
5181  *          field using decrRef() as it is no more needed. 
5182  *  \throw If the coordinates array is not set.
5183  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5184  *  \throw If the connectivity data array has more than one component.
5185  *  \throw If the connectivity data array has a named component.
5186  *  \throw If the connectivity index data array has more than one component.
5187  *  \throw If the connectivity index data array has a named component.
5188  *  \throw If \a this->getMeshDimension() != 2.
5189  *  \throw If \a this->getSpaceDimension() != 3.
5190  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5191  */
5192 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
5193 {
5194   checkConsistencyLight();
5195   int spaceDim=getSpaceDimension();
5196   int meshDim=getMeshDimension();
5197   if(spaceDim!=3)
5198     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5199   if(meshDim!=2)
5200     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5201   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5202   ret->setMesh(this);
5203   int nbOfCells=getNumberOfCells();
5204   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5205   arr->alloc(nbOfCells,1);
5206   double *pt=arr->getPointer();
5207   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5208   const int *conn=_nodal_connec->begin();
5209   const int *connI=_nodal_connec_index->begin();
5210   const double *coo=_coords->begin();
5211   double tmp[12];
5212   for(int i=0;i<nbOfCells;i++,pt++)
5213     {
5214       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5215       switch(t)
5216       {
5217         case INTERP_KERNEL::NORM_QUAD4:
5218           {
5219             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5220             *pt=INTERP_KERNEL::quadWarp(tmp);
5221             break;
5222           }
5223         default:
5224           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5225       }
5226       conn+=connI[i+1]-connI[i];
5227     }
5228   ret->setName("Warp");
5229   ret->synchronizeTimeWithSupport();
5230   return ret.retn();
5231 }
5232
5233
5234 /*!
5235  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
5236  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
5237  * treated: INTERP_KERNEL::NORM_QUAD4.
5238  * The skew is computed as follow for a quad with points (a,b,c,d): let
5239  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
5240  * then the skew is computed as:
5241  *  \f[
5242  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
5243  *  \f]
5244  *
5245  * For a cell of other type an exception is thrown.
5246  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5247  *          cells and one time, lying on \a this mesh. The caller is to delete this
5248  *          field using decrRef() as it is no more needed. 
5249  *  \throw If the coordinates array is not set.
5250  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5251  *  \throw If the connectivity data array has more than one component.
5252  *  \throw If the connectivity data array has a named component.
5253  *  \throw If the connectivity index data array has more than one component.
5254  *  \throw If the connectivity index data array has a named component.
5255  *  \throw If \a this->getMeshDimension() != 2.
5256  *  \throw If \a this->getSpaceDimension() != 3.
5257  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5258  */
5259 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
5260 {
5261   checkConsistencyLight();
5262   int spaceDim=getSpaceDimension();
5263   int meshDim=getMeshDimension();
5264   if(spaceDim!=3)
5265     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5266   if(meshDim!=2)
5267     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5268   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5269   ret->setMesh(this);
5270   int nbOfCells=getNumberOfCells();
5271   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5272   arr->alloc(nbOfCells,1);
5273   double *pt=arr->getPointer();
5274   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5275   const int *conn=_nodal_connec->begin();
5276   const int *connI=_nodal_connec_index->begin();
5277   const double *coo=_coords->begin();
5278   double tmp[12];
5279   for(int i=0;i<nbOfCells;i++,pt++)
5280     {
5281       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5282       switch(t)
5283       {
5284         case INTERP_KERNEL::NORM_QUAD4:
5285           {
5286             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5287             *pt=INTERP_KERNEL::quadSkew(tmp);
5288             break;
5289           }
5290         default:
5291           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5292       }
5293       conn+=connI[i+1]-connI[i];
5294     }
5295   ret->setName("Skew");
5296   ret->synchronizeTimeWithSupport();
5297   return ret.retn();
5298 }
5299
5300 /*!
5301  * 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.
5302  *
5303  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
5304  *
5305  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
5306  */
5307 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
5308 {
5309   checkConsistencyLight();
5310   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
5311   ret->setMesh(this);
5312   std::set<INTERP_KERNEL::NormalizedCellType> types;
5313   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
5314   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
5315   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
5316   arr->alloc(nbCells,1);
5317   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
5318     {
5319       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
5320       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
5321       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
5322     }
5323   ret->setArray(arr);
5324   ret->setName("Diameter");
5325   return ret.retn();
5326 }
5327
5328 /*!
5329  * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax).
5330  * 
5331  * \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)
5332  *                         For all other cases this input parameter is ignored.
5333  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5334  * 
5335  * \throw If \a this is not fully set (coordinates and connectivity).
5336  * \throw If a cell in \a this has no valid nodeId.
5337  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5338  */
5339 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
5340 {
5341   int mDim(getMeshDimension()),sDim(getSpaceDimension());
5342   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.
5343     return getBoundingBoxForBBTreeFast();
5344   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
5345     {
5346       bool presenceOfQuadratic(false);
5347       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
5348         {
5349           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
5350           if(cm.isQuadratic())
5351             presenceOfQuadratic=true;
5352         }
5353       if(!presenceOfQuadratic)
5354         return getBoundingBoxForBBTreeFast();
5355       if(mDim==2 && sDim==2)
5356         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
5357       else
5358         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
5359     }
5360   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) !");
5361 }
5362
5363 /*!
5364  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
5365  * So meshes having quadratic cells the computed bounding boxes can be invalid !
5366  * 
5367  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5368  * 
5369  * \throw If \a this is not fully set (coordinates and connectivity).
5370  * \throw If a cell in \a this has no valid nodeId.
5371  */
5372 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
5373 {
5374   checkFullyDefined();
5375   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
5376   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5377   double *bbox(ret->getPointer());
5378   for(int i=0;i<nbOfCells*spaceDim;i++)
5379     {
5380       bbox[2*i]=std::numeric_limits<double>::max();
5381       bbox[2*i+1]=-std::numeric_limits<double>::max();
5382     }
5383   const double *coordsPtr(_coords->begin());
5384   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5385   for(int i=0;i<nbOfCells;i++)
5386     {
5387       int offset=connI[i]+1;
5388       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
5389       for(int j=0;j<nbOfNodesForCell;j++)
5390         {
5391           int nodeId=conn[offset+j];
5392           if(nodeId>=0 && nodeId<nbOfNodes)
5393             {
5394               for(int k=0;k<spaceDim;k++)
5395                 {
5396                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5397                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5398                 }
5399               kk++;
5400             }
5401         }
5402       if(kk==0)
5403         {
5404           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
5405           throw INTERP_KERNEL::Exception(oss.str());
5406         }
5407     }
5408   return ret.retn();
5409 }
5410
5411 /*!
5412  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
5413  * useful for 2D meshes having quadratic cells
5414  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5415  * the two extremities of the arc of circle).
5416  * 
5417  * \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)
5418  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5419  * \throw If \a this is not fully defined.
5420  * \throw If \a this is not a mesh with meshDimension equal to 2.
5421  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5422  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
5423  */
5424 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
5425 {
5426   checkFullyDefined();
5427   INTERP_KERNEL::QuadraticPlanarArcDetectionPrecision arcPrec(arcDetEps);
5428
5429   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5430   if(spaceDim!=2 || mDim!=2)
5431     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!");
5432   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5433   double *bbox(ret->getPointer());
5434   const double *coords(_coords->begin());
5435   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5436   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5437     {
5438       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5439       int sz(connI[1]-connI[0]-1);
5440       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5441       INTERP_KERNEL::QuadraticPolygon *pol(0);
5442       for(int j=0;j<sz;j++)
5443         {
5444           int nodeId(conn[*connI+1+j]);
5445           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5446         }
5447       if(!cm.isQuadratic())
5448         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
5449       else
5450         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
5451       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
5452       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
5453     }
5454   return ret.retn();
5455 }
5456
5457 /*!
5458  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
5459  * useful for 2D meshes having quadratic cells
5460  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5461  * the two extremities of the arc of circle).
5462  * 
5463  * \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)
5464  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5465  * \throw If \a this is not fully defined.
5466  * \throw If \a this is not a mesh with meshDimension equal to 1.
5467  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5468  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5469  */
5470 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
5471 {
5472   checkFullyDefined();
5473   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5474   if(spaceDim!=2 || mDim!=1)
5475     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!");
5476   INTERP_KERNEL::QuadraticPlanarArcDetectionPrecision arcPrec(arcDetEps);
5477   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5478   double *bbox(ret->getPointer());
5479   const double *coords(_coords->begin());
5480   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5481   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5482     {
5483       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5484       int sz(connI[1]-connI[0]-1);
5485       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5486       INTERP_KERNEL::Edge *edge(0);
5487       for(int j=0;j<sz;j++)
5488         {
5489           int nodeId(conn[*connI+1+j]);
5490           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5491         }
5492       if(!cm.isQuadratic())
5493         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
5494       else
5495         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
5496       const INTERP_KERNEL::Bounds& b(edge->getBounds());
5497       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
5498     }
5499   return ret.retn();
5500 }
5501
5502 /// @cond INTERNAL
5503
5504 namespace MEDCouplingImpl
5505 {
5506   class ConnReader
5507   {
5508   public:
5509     ConnReader(const int *c, int val):_conn(c),_val(val) { }
5510     bool operator() (const int& pos) { return _conn[pos]!=_val; }
5511   private:
5512     const int *_conn;
5513     int _val;
5514   };
5515
5516   class ConnReader2
5517   {
5518   public:
5519     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5520     bool operator() (const int& pos) { return _conn[pos]==_val; }
5521   private:
5522     const int *_conn;
5523     int _val;
5524   };
5525 }
5526
5527 /// @endcond
5528
5529 /*!
5530  * This method expects that \a this is sorted by types. If not an exception will be thrown.
5531  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5532  * \a this is composed in cell types.
5533  * The returned array is of size 3*n where n is the number of different types present in \a this. 
5534  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
5535  * This parameter is kept only for compatibility with other methode listed above.
5536  */
5537 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
5538 {
5539   checkConnectivityFullyDefined();
5540   const int *conn=_nodal_connec->begin();
5541   const int *connI=_nodal_connec_index->begin();
5542   const int *work=connI;
5543   int nbOfCells=getNumberOfCells();
5544   std::size_t n=getAllGeoTypes().size();
5545   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
5546   std::set<INTERP_KERNEL::NormalizedCellType> types;
5547   for(std::size_t i=0;work!=connI+nbOfCells;i++)
5548     {
5549       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5550       if(types.find(typ)!=types.end())
5551         {
5552           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5553           oss << " is not contiguous !";
5554           throw INTERP_KERNEL::Exception(oss.str());
5555         }
5556       types.insert(typ);
5557       ret[3*i]=typ;
5558       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
5559       ret[3*i+1]=(int)std::distance(work,work2);
5560       work=work2;
5561     }
5562   return ret;
5563 }
5564
5565 /*!
5566  * This method is used to check that this has contiguous cell type in same order than described in \a code.
5567  * only for types cell, type node is not managed.
5568  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
5569  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5570  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5571  * If 2 or more same geometric type is in \a code and exception is thrown too.
5572  *
5573  * This method firstly checks
5574  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5575  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5576  * an exception is thrown too.
5577  * 
5578  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
5579  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
5580  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5581  */
5582 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
5583 {
5584   if(code.empty())
5585     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5586   std::size_t sz=code.size();
5587   std::size_t n=sz/3;
5588   if(sz%3!=0)
5589     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5590   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5591   int nb=0;
5592   bool isNoPflUsed=true;
5593   for(std::size_t i=0;i<n;i++)
5594     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5595       {
5596         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5597         nb+=code[3*i+1];
5598         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5599           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5600         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
5601       }
5602   if(types.size()!=n)
5603     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5604   if(isNoPflUsed)
5605     {
5606       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5607         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5608       if(types.size()==_types.size())
5609         return 0;
5610     }
5611   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5612   ret->alloc(nb,1);
5613   int *retPtr=ret->getPointer();
5614   const int *connI=_nodal_connec_index->begin();
5615   const int *conn=_nodal_connec->begin();
5616   int nbOfCells=getNumberOfCells();
5617   const int *i=connI;
5618   int kk=0;
5619   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5620     {
5621       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
5622       int offset=(int)std::distance(connI,i);
5623       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
5624       int nbOfCellsOfCurType=(int)std::distance(i,j);
5625       if(code[3*kk+2]==-1)
5626         for(int k=0;k<nbOfCellsOfCurType;k++)
5627           *retPtr++=k+offset;
5628       else
5629         {
5630           int idInIdsPerType=code[3*kk+2];
5631           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
5632             {
5633               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
5634               if(zePfl)
5635                 {
5636                   zePfl->checkAllocated();
5637                   if(zePfl->getNumberOfComponents()==1)
5638                     {
5639                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
5640                         {
5641                           if(*k>=0 && *k<nbOfCellsOfCurType)
5642                             *retPtr=(*k)+offset;
5643                           else
5644                             {
5645                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
5646                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
5647                               throw INTERP_KERNEL::Exception(oss.str());
5648                             }
5649                         }
5650                     }
5651                   else
5652                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
5653                 }
5654               else
5655                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
5656             }
5657           else
5658             {
5659               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
5660               oss << " should be in [0," << idsPerType.size() << ") !";
5661               throw INTERP_KERNEL::Exception(oss.str());
5662             }
5663         }
5664       i=j;
5665     }
5666   return ret.retn();
5667 }
5668
5669 /*!
5670  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
5671  * 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.
5672  * 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.
5673  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
5674  * 
5675  * \param [in] profile
5676  * \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.
5677  * \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,
5678  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5679  * \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.
5680  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5681  * \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
5682  */
5683 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
5684 {
5685   if(!profile)
5686     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
5687   if(profile->getNumberOfComponents()!=1)
5688     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5689   checkConnectivityFullyDefined();
5690   const int *conn=_nodal_connec->begin();
5691   const int *connI=_nodal_connec_index->begin();
5692   int nbOfCells=getNumberOfCells();
5693   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5694   std::vector<int> typeRangeVals(1);
5695   for(const int *i=connI;i!=connI+nbOfCells;)
5696     {
5697       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5698       if(std::find(types.begin(),types.end(),curType)!=types.end())
5699         {
5700           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5701         }
5702       types.push_back(curType);
5703       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5704       typeRangeVals.push_back((int)std::distance(connI,i));
5705     }
5706   //
5707   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5708   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5709   MCAuto<DataArrayInt> tmp0=castArr;
5710   MCAuto<DataArrayInt> tmp1=rankInsideCast;
5711   MCAuto<DataArrayInt> tmp2=castsPresent;
5712   //
5713   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5714   code.resize(3*nbOfCastsFinal);
5715   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
5716   std::vector< MCAuto<DataArrayInt> > idsPerType2;
5717   for(int i=0;i<nbOfCastsFinal;i++)
5718     {
5719       int castId=castsPresent->getIJ(i,0);
5720       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
5721       idsInPflPerType2.push_back(tmp3);
5722       code[3*i]=(int)types[castId];
5723       code[3*i+1]=tmp3->getNumberOfTuples();
5724       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->begin(),tmp3->begin()+tmp3->getNumberOfTuples());
5725       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
5726         {
5727           tmp4->copyStringInfoFrom(*profile);
5728           idsPerType2.push_back(tmp4);
5729           code[3*i+2]=(int)idsPerType2.size()-1;
5730         }
5731       else
5732         {
5733           code[3*i+2]=-1;
5734         }
5735     }
5736   std::size_t sz2=idsInPflPerType2.size();
5737   idsInPflPerType.resize(sz2);
5738   for(std::size_t i=0;i<sz2;i++)
5739     {
5740       DataArrayInt *locDa=idsInPflPerType2[i];
5741       locDa->incrRef();
5742       idsInPflPerType[i]=locDa;
5743     }
5744   std::size_t sz=idsPerType2.size();
5745   idsPerType.resize(sz);
5746   for(std::size_t i=0;i<sz;i++)
5747     {
5748       DataArrayInt *locDa=idsPerType2[i];
5749       locDa->incrRef();
5750       idsPerType[i]=locDa;
5751     }
5752 }
5753
5754 /*!
5755  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5756  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5757  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5758  * 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.
5759  */
5760 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
5761 {
5762   checkFullyDefined();
5763   nM1LevMesh->checkFullyDefined();
5764   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5765     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5766   if(_coords!=nM1LevMesh->getCoords())
5767     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5768   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
5769   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
5770   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5771   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5772   desc->transformWithIndArr(ret0->begin(),ret0->begin()+ret0->getNbOfElems());
5773   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5774   tmp->setConnectivity(tmp0,tmp1);
5775   tmp->renumberCells(ret0->begin(),false);
5776   revDesc=tmp->getNodalConnectivity();
5777   revDescIndx=tmp->getNodalConnectivityIndex();
5778   DataArrayInt *ret=0;
5779   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5780     {
5781       int tmp2;
5782       ret->getMaxValue(tmp2);
5783       ret->decrRef();
5784       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5785       throw INTERP_KERNEL::Exception(oss.str());
5786     }
5787   nM1LevMeshIds=ret;
5788   //
5789   revDesc->incrRef();
5790   revDescIndx->incrRef();
5791   ret1->incrRef();
5792   ret0->incrRef();
5793   meshnM1Old2New=ret0;
5794   return ret1;
5795 }
5796
5797 /*!
5798  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
5799  * necessary for writing the mesh to MED file. Additionally returns a permutation array
5800  * in "Old to New" mode.
5801  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
5802  *          this array using decrRef() as it is no more needed.
5803  *  \throw If the nodal connectivity of cells is not defined.
5804  */
5805 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
5806 {
5807   checkConnectivityFullyDefined();
5808   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
5809   renumberCells(ret->begin(),false);
5810   return ret.retn();
5811 }
5812
5813 /*!
5814  * This methods checks that cells are sorted by their types.
5815  * This method makes asumption (no check) that connectivity is correctly set before calling.
5816  */
5817 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5818 {
5819   checkFullyDefined();
5820   const int *conn=_nodal_connec->begin();
5821   const int *connI=_nodal_connec_index->begin();
5822   int nbOfCells=getNumberOfCells();
5823   std::set<INTERP_KERNEL::NormalizedCellType> types;
5824   for(const int *i=connI;i!=connI+nbOfCells;)
5825     {
5826       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5827       if(types.find(curType)!=types.end())
5828         return false;
5829       types.insert(curType);
5830       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5831     }
5832   return true;
5833 }
5834
5835 /*!
5836  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
5837  * The geometric type order is specified by MED file.
5838  * 
5839  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
5840  */
5841 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
5842 {
5843   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5844 }
5845
5846 /*!
5847  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5848  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
5849  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
5850  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
5851  */
5852 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5853 {
5854   checkFullyDefined();
5855   const int *conn=_nodal_connec->begin();
5856   const int *connI=_nodal_connec_index->begin();
5857   int nbOfCells=getNumberOfCells();
5858   if(nbOfCells==0)
5859     return true;
5860   int lastPos=-1;
5861   std::set<INTERP_KERNEL::NormalizedCellType> sg;
5862   for(const int *i=connI;i!=connI+nbOfCells;)
5863     {
5864       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5865       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
5866       if(isTypeExists!=orderEnd)
5867         {
5868           int pos=(int)std::distance(orderBg,isTypeExists);
5869           if(pos<=lastPos)
5870             return false;
5871           lastPos=pos;
5872           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5873         }
5874       else
5875         {
5876           if(sg.find(curType)==sg.end())
5877             {
5878               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5879               sg.insert(curType);
5880             }
5881           else
5882             return false;
5883         }
5884     }
5885   return true;
5886 }
5887
5888 /*!
5889  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5890  * 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
5891  * 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'.
5892  */
5893 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
5894 {
5895   checkConnectivityFullyDefined();
5896   int nbOfCells=getNumberOfCells();
5897   const int *conn=_nodal_connec->begin();
5898   const int *connI=_nodal_connec_index->begin();
5899   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
5900   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
5901   tmpa->alloc(nbOfCells,1);
5902   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
5903   tmpb->fillWithZero();
5904   int *tmp=tmpa->getPointer();
5905   int *tmp2=tmpb->getPointer();
5906   for(const int *i=connI;i!=connI+nbOfCells;i++)
5907     {
5908       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
5909       if(where!=orderEnd)
5910         {
5911           int pos=(int)std::distance(orderBg,where);
5912           tmp2[pos]++;
5913           tmp[std::distance(connI,i)]=pos;
5914         }
5915       else
5916         {
5917           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
5918           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
5919           oss << " has a type " << cm.getRepr() << " not in input array of type !";
5920           throw INTERP_KERNEL::Exception(oss.str());
5921         }
5922     }
5923   nbPerType=tmpb.retn();
5924   return tmpa.retn();
5925 }
5926
5927 /*!
5928  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
5929  *
5930  * \return a new object containing the old to new correspondance.
5931  *
5932  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5933  */
5934 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
5935 {
5936   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5937 }
5938
5939 /*!
5940  * 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.
5941  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
5942  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
5943  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
5944  */
5945 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5946 {
5947   DataArrayInt *nbPerType=0;
5948   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
5949   nbPerType->decrRef();
5950   return tmpa->buildPermArrPerLevel();
5951 }
5952
5953 /*!
5954  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
5955  * The number of cells remains unchanged after the call of this method.
5956  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
5957  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5958  *
5959  * \return the array giving the correspondance old to new.
5960  */
5961 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
5962 {
5963   checkFullyDefined();
5964   computeTypes();
5965   const int *conn=_nodal_connec->begin();
5966   const int *connI=_nodal_connec_index->begin();
5967   int nbOfCells=getNumberOfCells();
5968   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5969   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
5970     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
5971       {
5972         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5973         types.push_back(curType);
5974         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
5975       }
5976   DataArrayInt *ret=DataArrayInt::New();
5977   ret->alloc(nbOfCells,1);
5978   int *retPtr=ret->getPointer();
5979   std::fill(retPtr,retPtr+nbOfCells,-1);
5980   int newCellId=0;
5981   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5982     {
5983       for(const int *i=connI;i!=connI+nbOfCells;i++)
5984         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5985           retPtr[std::distance(connI,i)]=newCellId++;
5986     }
5987   renumberCells(retPtr,false);
5988   return ret;
5989 }
5990
5991 /*!
5992  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
5993  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
5994  * This method makes asumption that connectivity is correctly set before calling.
5995  */
5996 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
5997 {
5998   checkConnectivityFullyDefined();
5999   const int *conn=_nodal_connec->begin();
6000   const int *connI=_nodal_connec_index->begin();
6001   int nbOfCells=getNumberOfCells();
6002   std::vector<MEDCouplingUMesh *> ret;
6003   for(const int *i=connI;i!=connI+nbOfCells;)
6004     {
6005       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6006       int beginCellId=(int)std::distance(connI,i);
6007       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
6008       int endCellId=(int)std::distance(connI,i);
6009       int sz=endCellId-beginCellId;
6010       int *cells=new int[sz];
6011       for(int j=0;j<sz;j++)
6012         cells[j]=beginCellId+j;
6013       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6014       delete [] cells;
6015       ret.push_back(m);
6016     }
6017   return ret;
6018 }
6019
6020 /*!
6021  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6022  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6023  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6024  *
6025  * \return a newly allocated instance, that the caller must manage.
6026  * \throw If \a this contains more than one geometric type.
6027  * \throw If the nodal connectivity of \a this is not fully defined.
6028  * \throw If the internal data is not coherent.
6029  */
6030 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6031 {
6032   checkConnectivityFullyDefined();
6033   if(_types.size()!=1)
6034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6035   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6036   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6037   ret->setCoords(getCoords());
6038   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6039   if(retC)
6040     {
6041       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6042       retC->setNodalConnectivity(c);
6043     }
6044   else
6045     {
6046       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6047       if(!retD)
6048         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6049       DataArrayInt *c=0,*ci=0;
6050       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6051       MCAuto<DataArrayInt> cs(c),cis(ci);
6052       retD->setNodalConnectivity(cs,cis);
6053     }
6054   return ret.retn();
6055 }
6056
6057 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6058 {
6059   checkConnectivityFullyDefined();
6060   if(_types.size()!=1)
6061     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6062   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6063   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6064   if(cm.isDynamic())
6065     {
6066       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6067       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6068       throw INTERP_KERNEL::Exception(oss.str());
6069     }
6070   int nbCells=getNumberOfCells();
6071   int typi=(int)typ;
6072   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6073   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6074   int *outPtr=connOut->getPointer();
6075   const int *conn=_nodal_connec->begin();
6076   const int *connI=_nodal_connec_index->begin();
6077   nbNodesPerCell++;
6078   for(int i=0;i<nbCells;i++,connI++)
6079     {
6080       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6081         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6082       else
6083         {
6084           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 << ") !";
6085           throw INTERP_KERNEL::Exception(oss.str());
6086         }
6087     }
6088   return connOut.retn();
6089 }
6090
6091 /*!
6092  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
6093  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
6094  * \param nodalConn
6095  * \param nodalConnI
6096  */
6097 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
6098 {
6099   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
6100   checkConnectivityFullyDefined();
6101   if(_types.size()!=1)
6102     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6103   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6104   if(lgth<nbCells)
6105     throw INTERP_KERNEL::Exception(msg0);
6106   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6107   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6108   int *cp(c->getPointer()),*cip(ci->getPointer());
6109   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6110   cip[0]=0;
6111   for(int i=0;i<nbCells;i++,cip++,incip++)
6112     {
6113       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6114       int delta(stop-strt);
6115       if(delta>=1)
6116         {
6117           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6118             cp=std::copy(incp+strt,incp+stop,cp);
6119           else
6120             throw INTERP_KERNEL::Exception(msg0);
6121         }
6122       else
6123         throw INTERP_KERNEL::Exception(msg0);
6124       cip[1]=cip[0]+delta;
6125     }
6126   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6127 }
6128
6129 /*!
6130  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6131  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6132  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6133  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6134  * are not used here to avoid the build of big permutation array.
6135  *
6136  * \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
6137  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6138  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6139  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6140  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6141  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6142  * \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
6143  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6144  */
6145 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6146                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6147                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
6148 {
6149   std::vector<const MEDCouplingUMesh *> ms2;
6150   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6151     if(*it)
6152       {
6153         (*it)->checkConnectivityFullyDefined();
6154         ms2.push_back(*it);
6155       }
6156   if(ms2.empty())
6157     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6158   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6159   int meshDim=ms2[0]->getMeshDimension();
6160   std::vector<const MEDCouplingUMesh *> m1ssm;
6161   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
6162   //
6163   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6164   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
6165   int fake=0,rk=0;
6166   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6167   ret1->alloc(0,1); ret2->alloc(0,1);
6168   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6169     {
6170       if(meshDim!=(*it)->getMeshDimension())
6171         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6172       if(refCoo!=(*it)->getCoords())
6173         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6174       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6175       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6176       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
6177       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6178         {
6179           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6180           m1ssmSingleAuto.push_back(singleCell);
6181           m1ssmSingle.push_back(singleCell);
6182           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6183         }
6184     }
6185   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6186   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6187   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6188   for(std::size_t i=0;i<m1ssm.size();i++)
6189     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6190   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6191   szOfCellGrpOfSameType=ret1->renumber(renum->begin());
6192   idInMsOfCellGrpOfSameType=ret2->renumber(renum->begin());
6193   return ret0.retn();
6194 }
6195
6196 /*!
6197  * This method returns a newly created DataArrayInt instance.
6198  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6199  */
6200 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
6201 {
6202   checkFullyDefined();
6203   const int *conn=_nodal_connec->begin();
6204   const int *connIndex=_nodal_connec_index->begin();
6205   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6206   for(const int *w=begin;w!=end;w++)
6207     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6208       ret->pushBackSilent(*w);
6209   return ret.retn();
6210 }
6211
6212 /*!
6213  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6214  * are in [0:getNumberOfCells())
6215  */
6216 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
6217 {
6218   checkFullyDefined();
6219   const int *conn=_nodal_connec->begin();
6220   const int *connI=_nodal_connec_index->begin();
6221   int nbOfCells=getNumberOfCells();
6222   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
6223   int *tmp=new int[nbOfCells];
6224   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6225     {
6226       int j=0;
6227       for(const int *i=connI;i!=connI+nbOfCells;i++)
6228         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6229           tmp[std::distance(connI,i)]=j++;
6230     }
6231   DataArrayInt *ret=DataArrayInt::New();
6232   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6233   ret->copyStringInfoFrom(*da);
6234   int *retPtr=ret->getPointer();
6235   const int *daPtr=da->begin();
6236   int nbOfElems=da->getNbOfElems();
6237   for(int k=0;k<nbOfElems;k++)
6238     retPtr[k]=tmp[daPtr[k]];
6239   delete [] tmp;
6240   return ret;
6241 }
6242
6243 /*!
6244  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6245  * This method \b works \b for mesh sorted by type.
6246  * cells whose ids is in 'idsPerGeoType' array.
6247  * This method conserves coords and name of mesh.
6248  */
6249 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6250 {
6251   std::vector<int> code=getDistributionOfTypes();
6252   std::size_t nOfTypesInThis=code.size()/3;
6253   int sz=0,szOfType=0;
6254   for(std::size_t i=0;i<nOfTypesInThis;i++)
6255     {
6256       if(code[3*i]!=type)
6257         sz+=code[3*i+1];
6258       else
6259         szOfType=code[3*i+1];
6260     }
6261   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6262     if(*work<0 || *work>=szOfType)
6263       {
6264         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6265         oss << ". It should be in [0," << szOfType << ") !";
6266         throw INTERP_KERNEL::Exception(oss.str());
6267       }
6268   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6269   int *idsPtr=idsTokeep->getPointer();
6270   int offset=0;
6271   for(std::size_t i=0;i<nOfTypesInThis;i++)
6272     {
6273       if(code[3*i]!=type)
6274         for(int j=0;j<code[3*i+1];j++)
6275           *idsPtr++=offset+j;
6276       else
6277         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6278       offset+=code[3*i+1];
6279     }
6280   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6281   ret->copyTinyInfoFrom(this);
6282   return ret.retn();
6283 }
6284
6285 /*!
6286  * This method returns a vector of size 'this->getNumberOfCells()'.
6287  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6288  */
6289 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
6290 {
6291   int ncell=getNumberOfCells();
6292   std::vector<bool> ret(ncell);
6293   const int *cI=getNodalConnectivityIndex()->begin();
6294   const int *c=getNodalConnectivity()->begin();
6295   for(int i=0;i<ncell;i++)
6296     {
6297       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6298       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6299       ret[i]=cm.isQuadratic();
6300     }
6301   return ret;
6302 }
6303
6304 /*!
6305  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6306  */
6307 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6308 {
6309   if(other->getType()!=UNSTRUCTURED)
6310     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6311   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6312   return MergeUMeshes(this,otherC);
6313 }
6314
6315 /*!
6316  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6317  * computed by averaging coordinates of cell nodes, so this method is not a right
6318  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6319  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6320  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6321  *          components. The caller is to delete this array using decrRef() as it is
6322  *          no more needed.
6323  *  \throw If the coordinates array is not set.
6324  *  \throw If the nodal connectivity of cells is not defined.
6325  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6326  */
6327 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
6328 {
6329   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6330   int spaceDim=getSpaceDimension();
6331   int nbOfCells=getNumberOfCells();
6332   ret->alloc(nbOfCells,spaceDim);
6333   ret->copyStringInfoFrom(*getCoords());
6334   double *ptToFill=ret->getPointer();
6335   const int *nodal=_nodal_connec->begin();
6336   const int *nodalI=_nodal_connec_index->begin();
6337   const double *coor=_coords->begin();
6338   for(int i=0;i<nbOfCells;i++)
6339     {
6340       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6341       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6342       ptToFill+=spaceDim;
6343     }
6344   return ret.retn();
6345 }
6346
6347 /*!
6348  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6349  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
6350  * 
6351  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6352  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6353  * 
6354  * \sa MEDCouplingUMesh::computeCellCenterOfMass
6355  * \throw If \a this is not fully defined (coordinates and connectivity)
6356  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6357  */
6358 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
6359 {
6360   checkFullyDefined();
6361   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6362   int spaceDim=getSpaceDimension();
6363   int nbOfCells=getNumberOfCells();
6364   int nbOfNodes=getNumberOfNodes();
6365   ret->alloc(nbOfCells,spaceDim);
6366   double *ptToFill=ret->getPointer();
6367   const int *nodal=_nodal_connec->begin();
6368   const int *nodalI=_nodal_connec_index->begin();
6369   const double *coor=_coords->begin();
6370   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6371     {
6372       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6373       std::fill(ptToFill,ptToFill+spaceDim,0.);
6374       if(type!=INTERP_KERNEL::NORM_POLYHED)
6375         {
6376           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6377             {
6378               if(*conn>=0 && *conn<nbOfNodes)
6379                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6380               else
6381                 {
6382                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
6383                   throw INTERP_KERNEL::Exception(oss.str());
6384                 }
6385             }
6386           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
6387           if(nbOfNodesInCell>0)
6388             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6389           else
6390             {
6391               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
6392               throw INTERP_KERNEL::Exception(oss.str());
6393             }
6394         }
6395       else
6396         {
6397           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
6398           s.erase(-1);
6399           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
6400             {
6401               if(*it>=0 && *it<nbOfNodes)
6402                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
6403               else
6404                 {
6405                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
6406                   throw INTERP_KERNEL::Exception(oss.str());
6407                 }
6408             }
6409           if(!s.empty())
6410             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
6411           else
6412             {
6413               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
6414               throw INTERP_KERNEL::Exception(oss.str());
6415             }
6416         }
6417     }
6418   return ret.retn();
6419 }
6420
6421 /*!
6422  * Returns a new DataArrayDouble holding barycenters of specified cells. The
6423  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
6424  * are specified via an array of cell ids. 
6425  *  \warning Validity of the specified cell ids is not checked! 
6426  *           Valid range is [ 0, \a this->getNumberOfCells() ).
6427  *  \param [in] begin - an array of cell ids of interest.
6428  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
6429  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
6430  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
6431  *          caller is to delete this array using decrRef() as it is no more needed. 
6432  *  \throw If the coordinates array is not set.
6433  *  \throw If the nodal connectivity of cells is not defined.
6434  *
6435  *  \if ENABLE_EXAMPLES
6436  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
6437  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
6438  *  \endif
6439  */
6440 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6441 {
6442   DataArrayDouble *ret=DataArrayDouble::New();
6443   int spaceDim=getSpaceDimension();
6444   int nbOfTuple=(int)std::distance(begin,end);
6445   ret->alloc(nbOfTuple,spaceDim);
6446   double *ptToFill=ret->getPointer();
6447   double *tmp=new double[spaceDim];
6448   const int *nodal=_nodal_connec->begin();
6449   const int *nodalI=_nodal_connec_index->begin();
6450   const double *coor=_coords->begin();
6451   for(const int *w=begin;w!=end;w++)
6452     {
6453       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6454       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6455       ptToFill+=spaceDim;
6456     }
6457   delete [] tmp;
6458   return ret;
6459 }
6460
6461 /*!
6462  * 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".
6463  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
6464  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
6465  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
6466  * This method is useful to detect 2D cells in 3D space that are not coplanar.
6467  * 
6468  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
6469  * \throw If spaceDim!=3 or meshDim!=2.
6470  * \throw If connectivity of \a this is invalid.
6471  * \throw If connectivity of a cell in \a this points to an invalid node.
6472  */
6473 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
6474 {
6475   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
6476   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6477   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
6478     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
6479   ret->alloc(nbOfCells,4);
6480   double *retPtr(ret->getPointer());
6481   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
6482   const double *coor(_coords->begin());
6483   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
6484     {
6485       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
6486       if(nodalI[1]-nodalI[0]>=4)
6487         {
6488           double aa[3]={coor[nodal[nodalI[0]+1+1]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6489                         coor[nodal[nodalI[0]+1+1]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6490                         coor[nodal[nodalI[0]+1+1]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]}
6491           ,bb[3]={coor[nodal[nodalI[0]+1+2]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6492                         coor[nodal[nodalI[0]+1+2]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6493                         coor[nodal[nodalI[0]+1+2]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]};
6494           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]};
6495           for(int j=0;j<3;j++)
6496             {
6497               int nodeId(nodal[nodalI[0]+1+j]);
6498               if(nodeId>=0 && nodeId<nbOfNodes)
6499                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
6500               else
6501                 {
6502                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
6503                   throw INTERP_KERNEL::Exception(oss.str());
6504                 }
6505             }
6506           if(sqrt(cc[0]*cc[0]+cc[1]*cc[1]+cc[2]*cc[2])>1e-7)
6507             {
6508               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6509               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6510             }
6511           else
6512             {
6513               if(nodalI[1]-nodalI[0]==4)
6514                 {
6515                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : cell" << i << " : Presence of The 3 colinear points !";
6516                   throw INTERP_KERNEL::Exception(oss.str());
6517                 }
6518               //
6519               double dd[3]={0.,0.,0.};
6520               for(int offset=nodalI[0]+1;offset<nodalI[1];offset++)
6521                 std::transform(coor+3*nodal[offset],coor+3*(nodal[offset]+1),dd,dd,std::plus<double>());
6522               int nbOfNodesInCell(nodalI[1]-nodalI[0]-1);
6523               std::transform(dd,dd+3,dd,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6524               std::copy(dd,dd+3,matrix+4*2);
6525               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6526               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6527             }
6528         }
6529       else
6530         {
6531           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
6532           throw INTERP_KERNEL::Exception(oss.str());
6533         }
6534     }
6535   return ret.retn();
6536 }
6537
6538 /*!
6539  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6540  * 
6541  */
6542 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
6543 {
6544   if(!da)
6545     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6546   da->checkAllocated();
6547   std::string name(da->getName());
6548   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(name,0));
6549   if(name.empty())
6550     ret->setName("Mesh");
6551   ret->setCoords(da);
6552   int nbOfTuples(da->getNumberOfTuples());
6553   MCAuto<DataArrayInt> c(DataArrayInt::New()),cI(DataArrayInt::New());
6554   c->alloc(2*nbOfTuples,1);
6555   cI->alloc(nbOfTuples+1,1);
6556   int *cp(c->getPointer()),*cip(cI->getPointer());
6557   *cip++=0;
6558   for(int i=0;i<nbOfTuples;i++)
6559     {
6560       *cp++=INTERP_KERNEL::NORM_POINT1;
6561       *cp++=i;
6562       *cip++=2*(i+1);
6563     }
6564   ret->setConnectivity(c,cI,true);
6565   return ret.retn();
6566 }
6567
6568 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::Build1DMeshFromCoords(DataArrayDouble *da)
6569 {
6570   if(!da)
6571     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build01MeshFromCoords : instance of DataArrayDouble must be not null !");
6572   da->checkAllocated();
6573   std::string name(da->getName());
6574   MCAuto<MEDCouplingUMesh> ret;
6575   {
6576     MCAuto<MEDCouplingCMesh> tmp(MEDCouplingCMesh::New());
6577     MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6578     arr->alloc(da->getNumberOfTuples());
6579     tmp->setCoordsAt(0,arr);
6580     ret=tmp->buildUnstructured();
6581   }
6582   ret->setCoords(da);
6583   if(name.empty())
6584     ret->setName("Mesh");
6585   else
6586     ret->setName(name);
6587   return ret;
6588 }
6589
6590 /*!
6591  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
6592  * Cells and nodes of
6593  * the first mesh precede cells and nodes of the second mesh within the result mesh.
6594  *  \param [in] mesh1 - the first mesh.
6595  *  \param [in] mesh2 - the second mesh.
6596  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6597  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6598  *          is no more needed.
6599  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6600  *  \throw If the coordinates array is not set in none of the meshes.
6601  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6602  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6603  */
6604 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6605 {
6606   std::vector<const MEDCouplingUMesh *> tmp(2);
6607   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6608   return MergeUMeshes(tmp);
6609 }
6610
6611 /*!
6612  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
6613  * Cells and nodes of
6614  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
6615  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
6616  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6617  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6618  *          is no more needed.
6619  *  \throw If \a a.size() == 0.
6620  *  \throw If \a a[ *i* ] == NULL.
6621  *  \throw If the coordinates array is not set in none of the meshes.
6622  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6623  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6624  */
6625 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const std::vector<const MEDCouplingUMesh *>& a)
6626 {
6627   std::size_t sz=a.size();
6628   if(sz==0)
6629     return MergeUMeshesLL(a);
6630   for(std::size_t ii=0;ii<sz;ii++)
6631     if(!a[ii])
6632       {
6633         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6634         throw INTERP_KERNEL::Exception(oss.str());
6635       }
6636   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
6637   std::vector< const MEDCouplingUMesh * > aa(sz);
6638   int spaceDim=-3;
6639   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6640     {
6641       const MEDCouplingUMesh *cur=a[i];
6642       const DataArrayDouble *coo=cur->getCoords();
6643       if(coo)
6644         spaceDim=coo->getNumberOfComponents();
6645     }
6646   if(spaceDim==-3)
6647     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6648   for(std::size_t i=0;i<sz;i++)
6649     {
6650       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6651       aa[i]=bb[i];
6652     }
6653   return MergeUMeshesLL(aa);
6654 }
6655
6656 /*!
6657  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
6658  * dimension and sharing the node coordinates array.
6659  * All cells of the first mesh precede all cells of the second mesh
6660  * within the result mesh.
6661  *  \param [in] mesh1 - the first mesh.
6662  *  \param [in] mesh2 - the second mesh.
6663  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6664  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6665  *          is no more needed.
6666  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6667  *  \throw If the meshes do not share the node coordinates array.
6668  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6669  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6670  */
6671 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6672 {
6673   std::vector<const MEDCouplingUMesh *> tmp(2);
6674   tmp[0]=mesh1; tmp[1]=mesh2;
6675   return MergeUMeshesOnSameCoords(tmp);
6676 }
6677
6678 /*!
6679  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6680  * dimension and sharing the node coordinates array.
6681  * All cells of the *i*-th mesh precede all cells of the
6682  * (*i*+1)-th mesh within the result mesh.
6683  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6684  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6685  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6686  *          is no more needed.
6687  *  \throw If \a a.size() == 0.
6688  *  \throw If \a a[ *i* ] == NULL.
6689  *  \throw If the meshes do not share the node coordinates array.
6690  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6691  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6692  */
6693 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6694 {
6695   if(meshes.empty())
6696     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6697   for(std::size_t ii=0;ii<meshes.size();ii++)
6698     if(!meshes[ii])
6699       {
6700         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6701         throw INTERP_KERNEL::Exception(oss.str());
6702       }
6703   const DataArrayDouble *coords=meshes.front()->getCoords();
6704   int meshDim=meshes.front()->getMeshDimension();
6705   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6706   int meshLgth=0;
6707   int meshIndexLgth=0;
6708   for(;iter!=meshes.end();iter++)
6709     {
6710       if(coords!=(*iter)->getCoords())
6711         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6712       if(meshDim!=(*iter)->getMeshDimension())
6713         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6714       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
6715       meshIndexLgth+=(*iter)->getNumberOfCells();
6716     }
6717   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
6718   nodal->alloc(meshLgth,1);
6719   int *nodalPtr=nodal->getPointer();
6720   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
6721   nodalIndex->alloc(meshIndexLgth+1,1);
6722   int *nodalIndexPtr=nodalIndex->getPointer();
6723   int offset=0;
6724   for(iter=meshes.begin();iter!=meshes.end();iter++)
6725     {
6726       const int *nod=(*iter)->getNodalConnectivity()->begin();
6727       const int *index=(*iter)->getNodalConnectivityIndex()->begin();
6728       int nbOfCells=(*iter)->getNumberOfCells();
6729       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
6730       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6731       if(iter!=meshes.begin())
6732         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6733       else
6734         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6735       offset+=meshLgth2;
6736     }
6737   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6738   ret->setName("merge");
6739   ret->setMeshDimension(meshDim);
6740   ret->setConnectivity(nodal,nodalIndex,true);
6741   ret->setCoords(coords);
6742   return ret;
6743 }
6744
6745 /*!
6746  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6747  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
6748  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
6749  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
6750  * New" mode are returned for each input mesh.
6751  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6752  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
6753  *          valid values [0,1,2], see zipConnectivityTraducer().
6754  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
6755  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
6756  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
6757  *          no more needed.
6758  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6759  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6760  *          is no more needed.
6761  *  \throw If \a meshes.size() == 0.
6762  *  \throw If \a meshes[ *i* ] == NULL.
6763  *  \throw If the meshes do not share the node coordinates array.
6764  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
6765  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
6766  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
6767  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
6768  */
6769 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6770 {
6771   //All checks are delegated to MergeUMeshesOnSameCoords
6772   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6773   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6774   corr.resize(meshes.size());
6775   std::size_t nbOfMeshes=meshes.size();
6776   int offset=0;
6777   const int *o2nPtr=o2n->begin();
6778   for(std::size_t i=0;i<nbOfMeshes;i++)
6779     {
6780       DataArrayInt *tmp=DataArrayInt::New();
6781       int curNbOfCells=meshes[i]->getNumberOfCells();
6782       tmp->alloc(curNbOfCells,1);
6783       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6784       offset+=curNbOfCells;
6785       tmp->setName(meshes[i]->getName());
6786       corr[i]=tmp;
6787     }
6788   return ret.retn();
6789 }
6790
6791 /*!
6792  * Makes all given meshes share the nodal connectivity array. The common connectivity
6793  * array is created by concatenating the connectivity arrays of all given meshes. All
6794  * the given meshes must be of the same space dimension but dimension of cells **can
6795  * differ**. This method is particulary useful in MEDLoader context to build a \ref
6796  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6797  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
6798  *  \param [in,out] meshes - a vector of meshes to update.
6799  *  \throw If any of \a meshes is NULL.
6800  *  \throw If the coordinates array is not set in any of \a meshes.
6801  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6802  *  \throw If \a meshes are of different space dimension.
6803  */
6804 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
6805 {
6806   std::size_t sz=meshes.size();
6807   if(sz==0 || sz==1)
6808     return;
6809   std::vector< const DataArrayDouble * > coords(meshes.size());
6810   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6811   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6812     {
6813       if((*it))
6814         {
6815           (*it)->checkConnectivityFullyDefined();
6816           const DataArrayDouble *coo=(*it)->getCoords();
6817           if(coo)
6818             *it2=coo;
6819           else
6820             {
6821               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6822               oss << " has no coordinate array defined !";
6823               throw INTERP_KERNEL::Exception(oss.str());
6824             }
6825         }
6826       else
6827         {
6828           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6829           oss << " is null !";
6830           throw INTERP_KERNEL::Exception(oss.str());
6831         }
6832     }
6833   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6834   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6835   int offset=(*it)->getNumberOfNodes();
6836   (*it++)->setCoords(res);
6837   for(;it!=meshes.end();it++)
6838     {
6839       int oldNumberOfNodes=(*it)->getNumberOfNodes();
6840       (*it)->setCoords(res);
6841       (*it)->shiftNodeNumbersInConn(offset);
6842       offset+=oldNumberOfNodes;
6843     }
6844 }
6845
6846 /*!
6847  * Merges nodes coincident with a given precision within all given meshes that share
6848  * the nodal connectivity array. The given meshes **can be of different** mesh
6849  * dimension. This method is particulary useful in MEDLoader context to build a \ref
6850  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6851  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
6852  *  \param [in,out] meshes - a vector of meshes to update.
6853  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
6854  *  \throw If any of \a meshes is NULL.
6855  *  \throw If the \a meshes do not share the same node coordinates array.
6856  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6857  */
6858 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
6859 {
6860   if(meshes.empty())
6861     return ;
6862   std::set<const DataArrayDouble *> s;
6863   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6864     {
6865       if(*it)
6866         s.insert((*it)->getCoords());
6867       else
6868         {
6869           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 !";
6870           throw INTERP_KERNEL::Exception(oss.str());
6871         }
6872     }
6873   if(s.size()!=1)
6874     {
6875       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 !";
6876       throw INTERP_KERNEL::Exception(oss.str());
6877     }
6878   const DataArrayDouble *coo=*(s.begin());
6879   if(!coo)
6880     return;
6881   //
6882   DataArrayInt *comm,*commI;
6883   coo->findCommonTuples(eps,-1,comm,commI);
6884   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
6885   int oldNbOfNodes=coo->getNumberOfTuples();
6886   int newNbOfNodes;
6887   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6888   if(oldNbOfNodes==newNbOfNodes)
6889     return ;
6890   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->begin(),newNbOfNodes);
6891   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6892     {
6893       (*it)->renumberNodesInConn(o2n->begin());
6894       (*it)->setCoords(newCoords);
6895     } 
6896 }
6897
6898
6899 /*!
6900  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
6901  */
6902 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6903 {
6904   std::size_t i, ip1;
6905   double v[3]={0.,0.,0.};
6906   std::size_t sz=std::distance(begin,end);
6907   if(isQuadratic)
6908     sz/=2;
6909   for(i=0;i<sz;i++)
6910     {
6911       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];
6912       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6913       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6914     }
6915   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6916
6917   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
6918   // SEG3 forming a circle):
6919   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
6920     {
6921       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
6922       for(std::size_t j=0;j<sz;j++)
6923         {
6924           if (j%2)  // current point i is quadratic, next point i+1 is standard
6925             {
6926               i = sz+j;
6927               ip1 = (j+1)%sz; // ip1 = "i+1"
6928             }
6929           else      // current point i is standard, next point i+1 is quadratic
6930             {
6931               i = j;
6932               ip1 = j+sz;
6933             }
6934           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
6935           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
6936           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
6937         }
6938       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6939     }
6940   return (ret>0.);
6941 }
6942
6943 /*!
6944  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
6945  */
6946 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6947 {
6948   std::vector<std::pair<int,int> > edges;
6949   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6950   const int *bgFace=begin;
6951   for(std::size_t i=0;i<nbOfFaces;i++)
6952     {
6953       const int *endFace=std::find(bgFace+1,end,-1);
6954       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6955       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6956         {
6957           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6958           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6959             return false;
6960           edges.push_back(p1);
6961         }
6962       bgFace=endFace+1;
6963     }
6964   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6965 }
6966
6967 /*!
6968  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
6969  */
6970 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
6971 {
6972   double vec0[3],vec1[3];
6973   std::size_t sz=std::distance(begin,end);
6974   if(sz%2!=0)
6975     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
6976   int nbOfNodes=(int)sz/2;
6977   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
6978   const double *pt0=coords+3*begin[0];
6979   const double *pt1=coords+3*begin[nbOfNodes];
6980   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
6981   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
6982 }
6983
6984 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
6985 {
6986   std::size_t sz=std::distance(begin,end);
6987   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
6988   std::size_t nbOfNodes(sz/2);
6989   std::copy(begin,end,(int *)tmp);
6990   for(std::size_t j=1;j<nbOfNodes;j++)
6991     {
6992       begin[j]=tmp[nbOfNodes-j];
6993       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
6994     }
6995 }
6996
6997 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
6998 {
6999   std::size_t sz=std::distance(begin,end);
7000   if(sz!=4)
7001     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
7002   double vec0[3],vec1[3];
7003   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7004   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]; 
7005   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;
7006 }
7007
7008 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7009 {
7010   std::size_t sz=std::distance(begin,end);
7011   if(sz!=5)
7012     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
7013   double vec0[3];
7014   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7015   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7016   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7017 }
7018
7019 /*!
7020  * 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 ) 
7021  * 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
7022  * a 2D space.
7023  *
7024  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7025  * \param [in] coords the coordinates with nb of components exactly equal to 3
7026  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7027  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7028  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7029  */
7030 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, int index, DataArrayInt *res, MEDCouplingUMesh *faces,
7031                                               DataArrayInt *E_Fi, DataArrayInt *E_F, DataArrayInt *F_Ei, DataArrayInt *F_E)
7032 {
7033   int nbFaces = E_Fi->getIJ(index + 1, 0) - E_Fi->getIJ(index, 0);
7034   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7035   double *vPtr=v->getPointer();
7036   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,2);
7037   double *pPtr=p->getPointer();
7038   int *e_fi = E_Fi->getPointer(), *e_f = E_F->getPointer(), *f_ei = F_Ei->getPointer(), *f_e = F_E->getPointer();
7039   const int *f_idx = faces->getNodalConnectivityIndex()->getPointer(), *f_cnn = faces->getNodalConnectivity()->getPointer();
7040   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7041     {
7042       int face = e_f[e_fi[index] + i];
7043       ComputeVecAndPtOfFace(eps, coords->begin(), f_cnn + f_idx[face] + 1, f_cnn + f_idx[face + 1], vPtr, pPtr);
7044       // to differentiate faces going to different cells:
7045       pPtr++, *pPtr = 0;
7046       for (int j = f_ei[face]; j < f_ei[face + 1]; j++)
7047         *pPtr += f_e[j];
7048     }
7049   pPtr=p->getPointer(); vPtr=v->getPointer();
7050   DataArrayInt *comm1=0,*commI1=0;
7051   v->findCommonTuples(eps,-1,comm1,commI1);
7052   for (int i = 0; i < nbFaces; i++)
7053     if (comm1->findIdFirstEqual(i) < 0)
7054       {
7055         comm1->pushBackSilent(i);
7056         commI1->pushBackSilent(comm1->getNumberOfTuples());
7057       }
7058   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7059   const int *comm1Ptr=comm1->begin();
7060   const int *commI1Ptr=commI1->begin();
7061   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7062   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7063   //
7064   for(int i=0;i<nbOfGrps1;i++)
7065     {
7066       int vecId=comm1Ptr[commI1Ptr[i]];
7067       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7068       DataArrayInt *comm2=0,*commI2=0;
7069       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7070       for (int j = 0; j < commI1Ptr[i+1] - commI1Ptr[i]; j++)
7071         if (comm2->findIdFirstEqual(j) < 0)
7072           {
7073             comm2->pushBackSilent(j);
7074             commI2->pushBackSilent(comm2->getNumberOfTuples());
7075           }
7076       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7077       const int *comm2Ptr=comm2->begin();
7078       const int *commI2Ptr=commI2->begin();
7079       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7080       for(int j=0;j<nbOfGrps2;j++)
7081         {
7082           if(commI2Ptr[j+1] == commI2Ptr[j] + 1)
7083             {
7084               int face = e_f[e_fi[index] + comm1Ptr[commI1Ptr[i] + comm2Ptr[commI2Ptr[j]]]]; //hmmm
7085               res->insertAtTheEnd(f_cnn + f_idx[face] + 1, f_cnn + f_idx[face + 1]);
7086               res->pushBackSilent(-1);
7087             }
7088           else
7089             {
7090               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7091               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
7092               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7093               ids2->transformWithIndArr(e_f + e_fi[index], e_f + e_fi[index + 1]);
7094               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(faces->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7095               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7096               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7097               const int *idsNodePtr=idsNode->begin();
7098               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];
7099               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7100               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7101               if(std::abs(norm)>eps)
7102                 {
7103                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7104                   mm3->rotate(center,vec,angle);
7105                 }
7106               mm3->changeSpaceDimension(2);
7107               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7108               const int *conn4=mm4->getNodalConnectivity()->begin();
7109               const int *connI4=mm4->getNodalConnectivityIndex()->begin();
7110               int nbOfCells=mm4->getNumberOfCells();
7111               for(int k=0;k<nbOfCells;k++)
7112                 {
7113                   int l=0;
7114                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7115                     res->pushBackSilent(idsNodePtr[*work]);
7116                   res->pushBackSilent(-1);
7117                 }
7118             }
7119         }
7120     }
7121   res->popBackSilent();
7122 }
7123
7124 /*!
7125  * 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
7126  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7127  * 
7128  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7129  * \param [in] coords coordinates expected to have 3 components.
7130  * \param [in] begin start of the nodal connectivity of the face.
7131  * \param [in] end end of the nodal connectivity (excluded) of the face.
7132  * \param [out] v the normalized vector of size 3
7133  * \param [out] p the pos of plane
7134  */
7135 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
7136 {
7137   std::size_t nbPoints=std::distance(begin,end);
7138   if(nbPoints<3)
7139     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7140   double vec[3]={0.,0.,0.};
7141   std::size_t j=0;
7142   bool refFound=false;
7143   for(;j<nbPoints-1 && !refFound;j++)
7144     {
7145       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7146       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7147       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7148       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7149       if(norm>eps)
7150         {
7151           refFound=true;
7152           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7153         }
7154     }
7155   for(std::size_t i=j;i<nbPoints-1;i++)
7156     {
7157       double curVec[3];
7158       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7159       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7160       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7161       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7162       if(norm<eps)
7163         continue;
7164       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7165       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];
7166       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7167       if(norm>eps)
7168         {
7169           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7170           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7171           return ;
7172         }
7173     }
7174   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7175 }
7176
7177 /*!
7178  * This method tries to obtain a well oriented polyhedron.
7179  * If the algorithm fails, an exception will be thrown.
7180  */
7181 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
7182 {
7183   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7184   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7185   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7186   isPerm[0]=true;
7187   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7188   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7189   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7190   //
7191   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7192     {
7193       bgFace=begin;
7194       std::size_t smthChanged=0;
7195       for(std::size_t i=0;i<nbOfFaces;i++)
7196         {
7197           endFace=std::find(bgFace+1,end,-1);
7198           nbOfEdgesInFace=std::distance(bgFace,endFace);
7199           if(!isPerm[i])
7200             {
7201               bool b;
7202               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7203                 {
7204                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7205                   std::pair<int,int> p2(p1.second,p1.first);
7206                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7207                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7208                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7209                 }
7210               if(isPerm[i])
7211                 { 
7212                   if(!b)
7213                     std::reverse(bgFace+1,endFace);
7214                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7215                     {
7216                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7217                       std::pair<int,int> p2(p1.second,p1.first);
7218                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7219                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7220                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7221                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7222                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7223                       if(it!=edgesOK.end())
7224                         {
7225                           edgesOK.erase(it);
7226                           edgesFinished.push_back(p1);
7227                         }
7228                       else
7229                         edgesOK.push_back(p1);
7230                     }
7231                 }
7232             }
7233           bgFace=endFace+1;
7234         }
7235       if(smthChanged==0)
7236         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7237     }
7238   if(!edgesOK.empty())
7239     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7240   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7241     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7242       bgFace=begin;
7243       for(std::size_t i=0;i<nbOfFaces;i++)
7244         {
7245           endFace=std::find(bgFace+1,end,-1);
7246           std::reverse(bgFace+1,endFace);
7247           bgFace=endFace+1;
7248         }
7249     }
7250 }
7251
7252
7253 /*!
7254  * This method makes the assumption spacedimension == meshdimension == 2.
7255  * This method works only for linear cells.
7256  * 
7257  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7258  */
7259 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
7260 {
7261   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7262     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7263   MCAuto<MEDCouplingUMesh> skin(computeSkin());
7264   int oldNbOfNodes(skin->getNumberOfNodes());
7265   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
7266   int nbOfNodesExpected(skin->getNumberOfNodes());
7267   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
7268   int nbCells(skin->getNumberOfCells());
7269   if(nbCells==nbOfNodesExpected)
7270     return buildUnionOf2DMeshLinear(skin,n2o);
7271   else if(2*nbCells==nbOfNodesExpected)
7272     return buildUnionOf2DMeshQuadratic(skin,n2o);
7273   else
7274     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
7275 }
7276
7277 /*!
7278  * This method makes the assumption spacedimension == meshdimension == 3.
7279  * This method works only for linear cells.
7280  * 
7281  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7282  */
7283 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
7284 {
7285   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7286     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7287   MCAuto<MEDCouplingUMesh> m=computeSkin();
7288   const int *conn=m->getNodalConnectivity()->begin();
7289   const int *connI=m->getNodalConnectivityIndex()->begin();
7290   int nbOfCells=m->getNumberOfCells();
7291   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7292   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7293   if(nbOfCells<1)
7294     return ret.retn();
7295   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7296   for(int i=1;i<nbOfCells;i++)
7297     {
7298       *work++=-1;
7299       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7300     }
7301   return ret.retn();
7302 }
7303
7304 /*!
7305  * \brief Creates a graph of cell neighbors
7306  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
7307  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
7308  *  For example
7309  *  - index:  0 3 5 6 6
7310  *  - value:  1 2 3 2 3 3
7311  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7312  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
7313  */
7314 MEDCouplingSkyLineArray* MEDCouplingUMesh::generateGraph() const
7315 {
7316   checkConnectivityFullyDefined();
7317
7318   int meshDim = this->getMeshDimension();
7319   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
7320   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
7321   this->getReverseNodalConnectivity(revConn,indexr);
7322   const int* indexr_ptr=indexr->begin();
7323   const int* revConn_ptr=revConn->begin();
7324
7325   const MEDCoupling::DataArrayInt* index;
7326   const MEDCoupling::DataArrayInt* conn;
7327   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
7328   index=this->getNodalConnectivityIndex();
7329   int nbCells=this->getNumberOfCells();
7330   const int* index_ptr=index->begin();
7331   const int* conn_ptr=conn->begin();
7332
7333   //creating graph arcs (cell to cell relations)
7334   //arcs are stored in terms of (index,value) notation
7335   // 0 3 5 6 6
7336   // 1 2 3 2 3 3
7337   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7338   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
7339
7340   //warning here one node have less than or equal effective number of cell with it
7341   //but cell could have more than effective nodes
7342   //because other equals nodes in other domain (with other global inode)
7343   std::vector <int> cell2cell_index(nbCells+1,0);
7344   std::vector <int> cell2cell;
7345   cell2cell.reserve(3*nbCells);
7346
7347   for (int icell=0; icell<nbCells;icell++)
7348     {
7349       std::map<int,int > counter;
7350       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
7351         {
7352           int inode=conn_ptr[iconn];
7353           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
7354             {
7355               int icell2=revConn_ptr[iconnr];
7356               std::map<int,int>::iterator iter=counter.find(icell2);
7357               if (iter!=counter.end()) (iter->second)++;
7358               else counter.insert(std::make_pair(icell2,1));
7359             }
7360         }
7361       for (std::map<int,int>::const_iterator iter=counter.begin();
7362            iter!=counter.end(); iter++)
7363         if (iter->second >= meshDim)
7364           {
7365             cell2cell_index[icell+1]++;
7366             cell2cell.push_back(iter->first);
7367           }
7368     }
7369   indexr->decrRef();
7370   revConn->decrRef();
7371   cell2cell_index[0]=0;
7372   for (int icell=0; icell<nbCells;icell++)
7373     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
7374
7375   //filling up index and value to create skylinearray structure
7376   MEDCouplingSkyLineArray * array(MEDCouplingSkyLineArray::New(cell2cell_index,cell2cell));
7377   return array;
7378 }
7379
7380
7381 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
7382 {
7383   int nbOfCells=getNumberOfCells();
7384   if(nbOfCells<=0)
7385     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7386   ofs << "  <" << getVTKDataSetType() << ">\n";
7387   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7388   ofs << "      <PointData>\n" << pointData << std::endl;
7389   ofs << "      </PointData>\n";
7390   ofs << "      <CellData>\n" << cellData << std::endl;
7391   ofs << "      </CellData>\n";
7392   ofs << "      <Points>\n";
7393   if(getSpaceDimension()==3)
7394     _coords->writeVTK(ofs,8,"Points",byteData);
7395   else
7396     {
7397       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7398       coo->writeVTK(ofs,8,"Points",byteData);
7399     }
7400   ofs << "      </Points>\n";
7401   ofs << "      <Cells>\n";
7402   const int *cPtr=_nodal_connec->begin();
7403   const int *cIPtr=_nodal_connec_index->begin();
7404   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7405   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7406   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7407   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7408   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7409   int szFaceOffsets=0,szConn=0;
7410   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7411     {
7412       *w2=cPtr[cIPtr[i]];
7413       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7414         {
7415           *w1=-1;
7416           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7417           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7418         }
7419       else
7420         {
7421           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7422           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7423           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7424           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7425           w4=std::copy(c.begin(),c.end(),w4);
7426         }
7427     }
7428   types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
7429   types->writeVTK(ofs,8,"UInt8","types",byteData);
7430   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
7431   if(szFaceOffsets!=0)
7432     {//presence of Polyhedra
7433       connectivity->reAlloc(szConn);
7434       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
7435       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7436       w1=faces->getPointer();
7437       for(int i=0;i<nbOfCells;i++)
7438         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7439           {
7440             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7441             *w1++=nbFaces;
7442             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7443             for(int j=0;j<nbFaces;j++)
7444               {
7445                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7446                 *w1++=(int)std::distance(w6,w5);
7447                 w1=std::copy(w6,w5,w1);
7448                 w6=w5+1;
7449               }
7450           }
7451       faces->writeVTK(ofs,8,"Int32","faces",byteData);
7452     }
7453   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
7454   ofs << "      </Cells>\n";
7455   ofs << "    </Piece>\n";
7456   ofs << "  </" << getVTKDataSetType() << ">\n";
7457 }
7458
7459 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
7460 {
7461   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
7462   if(_mesh_dim==-2)
7463     { stream << " Not set !"; return ; }
7464   stream << " Mesh dimension : " << _mesh_dim << ".";
7465   if(_mesh_dim==-1)
7466     return ;
7467   if(!_coords)
7468     { stream << " No coordinates set !"; return ; }
7469   if(!_coords->isAllocated())
7470     { stream << " Coordinates set but not allocated !"; return ; }
7471   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
7472   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
7473   if(!_nodal_connec_index)
7474     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
7475   if(!_nodal_connec_index->isAllocated())
7476     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
7477   int lgth=_nodal_connec_index->getNumberOfTuples();
7478   int cpt=_nodal_connec_index->getNumberOfComponents();
7479   if(cpt!=1 || lgth<1)
7480     return ;
7481   stream << std::endl << "Number of cells : " << lgth-1 << ".";
7482 }
7483
7484 std::string MEDCouplingUMesh::getVTKDataSetType() const
7485 {
7486   return std::string("UnstructuredGrid");
7487 }
7488
7489 std::string MEDCouplingUMesh::getVTKFileExtension() const
7490 {
7491   return std::string("vtu");
7492 }
7493
7494
7495
7496 /**
7497  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
7498  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
7499  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
7500  * The caller is to deal with the resulting DataArrayInt.
7501  *  \throw If the coordinate array is not set.
7502  *  \throw If the nodal connectivity of the cells is not defined.
7503  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
7504  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
7505  *
7506  * \sa DataArrayInt::sortEachPairToMakeALinkedList
7507  */
7508 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
7509 {
7510   checkFullyDefined();
7511   if(getMeshDimension()!=1)
7512     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
7513
7514   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
7515   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
7516   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
7517   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
7518   const int *d(_d->begin()), *dI(_dI->begin());
7519   const int *rD(_rD->begin()), *rDI(_rDI->begin());
7520   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
7521   const int * dsi(_dsi->begin());
7522   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
7523   m_points=0;
7524   if (dsii->getNumberOfTuples())
7525     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
7526
7527   int nc(getNumberOfCells());
7528   MCAuto<DataArrayInt> result(DataArrayInt::New());
7529   result->alloc(nc,1);
7530
7531   // set of edges not used so far
7532   std::set<int> edgeSet;
7533   for (int i=0; i<nc; edgeSet.insert(i), i++);
7534
7535   int startSeg=0;
7536   int newIdx=0;
7537   // while we have points with only one neighbor segments
7538   do
7539     {
7540       std::list<int> linePiece;
7541       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
7542       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
7543         {
7544           // Fill the list forward (resp. backward) from the start segment:
7545           int activeSeg = startSeg;
7546           int prevPointId = -20;
7547           int ptId;
7548           while (!edgeSet.empty())
7549             {
7550               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
7551                 {
7552                   if (direction==0)
7553                     linePiece.push_back(activeSeg);
7554                   else
7555                     linePiece.push_front(activeSeg);
7556                   edgeSet.erase(activeSeg);
7557                 }
7558
7559               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
7560               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
7561               if (dsi[ptId] == 1) // hitting the end of the line
7562                 break;
7563               prevPointId = ptId;
7564               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
7565               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
7566             }
7567         }
7568       // Done, save final piece into DA:
7569       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
7570       newIdx += linePiece.size();
7571
7572       // identify next valid start segment (one which is not consumed)
7573       if(!edgeSet.empty())
7574         startSeg = *(edgeSet.begin());
7575     }
7576   while (!edgeSet.empty());
7577   return result.retn();
7578 }
7579
7580 /**
7581  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
7582  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
7583  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
7584  * a minimal creation of new nodes is wanted.
7585  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
7586  * nodes if a SEG3 is split without information of middle.
7587  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
7588  * avoid to have a non conform mesh.
7589  *
7590  * \return int - the number of new nodes created (in most of cases 0).
7591  * 
7592  * \throw If \a this is not coherent.
7593  * \throw If \a this has not spaceDim equal to 2.
7594  * \throw If \a this has not meshDim equal to 2.
7595  * \throw If some subcells needed to be split are orphan.
7596  * \sa MEDCouplingUMesh::conformize2D
7597  */
7598 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
7599 {
7600   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
7601     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
7602   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
7603   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
7604     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
7605   if(midOpt==0 && midOptI==0)
7606     {
7607       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
7608       return 0;
7609     }
7610   else if(midOpt!=0 && midOptI!=0)
7611     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
7612   else
7613     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
7614 }
7615
7616 /*!
7617  * 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
7618  * 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
7619  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7620  * 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
7621  * 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.
7622  * 
7623  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7624  */
7625 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
7626 {
7627   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7628   if(sz>=4)
7629     {
7630       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7631       if(cm.getDimension()==2)
7632         {
7633           const int *node=nodalConnBg+1;
7634           int startNode=*node++;
7635           double refX=coords[2*startNode];
7636           for(;node!=nodalConnEnd;node++)
7637             {
7638               if(coords[2*(*node)]<refX)
7639                 {
7640                   startNode=*node;
7641                   refX=coords[2*startNode];
7642                 }
7643             }
7644           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7645           refX=1e300;
7646           double tmp1;
7647           double tmp2[2];
7648           double angle0=-M_PI/2;
7649           //
7650           int nextNode=-1;
7651           int prevNode=-1;
7652           double resRef;
7653           double angleNext=0.;
7654           while(nextNode!=startNode)
7655             {
7656               nextNode=-1;
7657               resRef=1e300;
7658               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7659                 {
7660                   if(*node!=tmpOut.back() && *node!=prevNode)
7661                     {
7662                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7663                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7664                       double res;
7665                       if(angleM<=angle0)
7666                         res=angle0-angleM;
7667                       else
7668                         res=angle0-angleM+2.*M_PI;
7669                       if(res<resRef)
7670                         {
7671                           nextNode=*node;
7672                           resRef=res;
7673                           angleNext=angleM;
7674                         }
7675                     }
7676                 }
7677               if(nextNode!=startNode)
7678                 {
7679                   angle0=angleNext-M_PI;
7680                   if(angle0<-M_PI)
7681                     angle0+=2*M_PI;
7682                   prevNode=tmpOut.back();
7683                   tmpOut.push_back(nextNode);
7684                 }
7685             }
7686           std::vector<int> tmp3(2*(sz-1));
7687           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7688           std::copy(nodalConnBg+1,nodalConnEnd,it);
7689           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7690             {
7691               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7692               return false;
7693             }
7694           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7695             {
7696               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7697               return false;
7698             }
7699           else
7700             {
7701               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7702               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7703               return true;
7704             }
7705         }
7706       else
7707         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7708     }
7709   else
7710     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7711 }
7712
7713 /*!
7714  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7715  * 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.
7716  * 
7717  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7718  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7719  * \param [in,out] arr array in which the remove operation will be done.
7720  * \param [in,out] arrIndx array in the remove operation will modify
7721  * \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])
7722  * \return true if \b arr and \b arrIndx have been modified, false if not.
7723  */
7724 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
7725 {
7726   if(!arrIndx || !arr)
7727     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7728   if(offsetForRemoval<0)
7729     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7730   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7731   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7732   int *arrIPtr=arrIndx->getPointer();
7733   *arrIPtr++=0;
7734   int previousArrI=0;
7735   const int *arrPtr=arr->begin();
7736   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7737   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7738     {
7739       if(*arrIPtr-previousArrI>offsetForRemoval)
7740         {
7741           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7742             {
7743               if(s.find(*work)==s.end())
7744                 arrOut.push_back(*work);
7745             }
7746         }
7747       previousArrI=*arrIPtr;
7748       *arrIPtr=(int)arrOut.size();
7749     }
7750   if(arr->getNumberOfTuples()==arrOut.size())
7751     return false;
7752   arr->alloc((int)arrOut.size(),1);
7753   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7754   return true;
7755 }
7756
7757 /*!
7758  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7759  * (\ref numbering-indirect).
7760  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7761  * The selection of extraction is done standardly in new2old format.
7762  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7763  *
7764  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7765  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7766  * \param [in] arrIn arr origin array from which the extraction will be done.
7767  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7768  * \param [out] arrOut the resulting array
7769  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7770  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
7771  */
7772 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7773                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7774 {
7775   if(!arrIn || !arrIndxIn)
7776     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7777   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7778   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7779     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
7780   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7781   const int *arrInPtr=arrIn->begin();
7782   const int *arrIndxPtr=arrIndxIn->begin();
7783   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7784   if(nbOfGrps<0)
7785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7786   int maxSizeOfArr=arrIn->getNumberOfTuples();
7787   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7788   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7789   arrIo->alloc((int)(sz+1),1);
7790   const int *idsIt=idsOfSelectBg;
7791   int *work=arrIo->getPointer();
7792   *work++=0;
7793   int lgth=0;
7794   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7795     {
7796       if(*idsIt>=0 && *idsIt<nbOfGrps)
7797         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7798       else
7799         {
7800           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7801           throw INTERP_KERNEL::Exception(oss.str());
7802         }
7803       if(lgth>=work[-1])
7804         *work=lgth;
7805       else
7806         {
7807           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7808           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7809           throw INTERP_KERNEL::Exception(oss.str());
7810         }
7811     }
7812   arro->alloc(lgth,1);
7813   work=arro->getPointer();
7814   idsIt=idsOfSelectBg;
7815   for(std::size_t i=0;i<sz;i++,idsIt++)
7816     {
7817       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7818         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7819       else
7820         {
7821           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7822           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7823           throw INTERP_KERNEL::Exception(oss.str());
7824         }
7825     }
7826   arrOut=arro.retn();
7827   arrIndexOut=arrIo.retn();
7828 }
7829
7830 /*!
7831  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7832  * (\ref numbering-indirect).
7833  * 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 ).
7834  * The selection of extraction is done standardly in new2old format.
7835  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7836  *
7837  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
7838  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
7839  * \param [in] idsOfSelectStep
7840  * \param [in] arrIn arr origin array from which the extraction will be done.
7841  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7842  * \param [out] arrOut the resulting array
7843  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7844  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
7845  */
7846 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7847                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7848 {
7849   if(!arrIn || !arrIndxIn)
7850     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
7851   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7852   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
7854   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
7855   const int *arrInPtr=arrIn->begin();
7856   const int *arrIndxPtr=arrIndxIn->begin();
7857   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7858   if(nbOfGrps<0)
7859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7860   int maxSizeOfArr=arrIn->getNumberOfTuples();
7861   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7862   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7863   arrIo->alloc((int)(sz+1),1);
7864   int idsIt=idsOfSelectStart;
7865   int *work=arrIo->getPointer();
7866   *work++=0;
7867   int lgth=0;
7868   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
7869     {
7870       if(idsIt>=0 && idsIt<nbOfGrps)
7871         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
7872       else
7873         {
7874           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7875           throw INTERP_KERNEL::Exception(oss.str());
7876         }
7877       if(lgth>=work[-1])
7878         *work=lgth;
7879       else
7880         {
7881           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
7882           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
7883           throw INTERP_KERNEL::Exception(oss.str());
7884         }
7885     }
7886   arro->alloc(lgth,1);
7887   work=arro->getPointer();
7888   idsIt=idsOfSelectStart;
7889   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
7890     {
7891       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
7892         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
7893       else
7894         {
7895           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
7896           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7897           throw INTERP_KERNEL::Exception(oss.str());
7898         }
7899     }
7900   arrOut=arro.retn();
7901   arrIndexOut=arrIo.retn();
7902 }
7903
7904 /*!
7905  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7906  * 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
7907  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7908  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7909  *
7910  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7911  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7912  * \param [in] arrIn arr origin array from which the extraction will be done.
7913  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7914  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
7915  * \param [in] srcArrIndex index array of \b srcArr
7916  * \param [out] arrOut the resulting array
7917  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7918  * 
7919  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7920  */
7921 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7922                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7923                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7924 {
7925   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7926     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7927   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7928   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7929   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7930   std::vector<bool> v(nbOfTuples,true);
7931   int offset=0;
7932   const int *arrIndxInPtr=arrIndxIn->begin();
7933   const int *srcArrIndexPtr=srcArrIndex->begin();
7934   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7935     {
7936       if(*it>=0 && *it<nbOfTuples)
7937         {
7938           v[*it]=false;
7939           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7940         }
7941       else
7942         {
7943           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7944           throw INTERP_KERNEL::Exception(oss.str());
7945         }
7946     }
7947   srcArrIndexPtr=srcArrIndex->begin();
7948   arrIo->alloc(nbOfTuples+1,1);
7949   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7950   const int *arrInPtr=arrIn->begin();
7951   const int *srcArrPtr=srcArr->begin();
7952   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7953   int *arroPtr=arro->getPointer();
7954   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7955     {
7956       if(v[ii])
7957         {
7958           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7959           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7960         }
7961       else
7962         {
7963           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7964           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7965           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7966         }
7967     }
7968   arrOut=arro.retn();
7969   arrIndexOut=arrIo.retn();
7970 }
7971
7972 /*!
7973  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7974  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7975  *
7976  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7977  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7978  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7979  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7980  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
7981  * \param [in] srcArrIndex index array of \b srcArr
7982  * 
7983  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
7984  */
7985 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7986                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
7987 {
7988   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7989     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7990   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7991   const int *arrIndxInPtr=arrIndxIn->begin();
7992   const int *srcArrIndexPtr=srcArrIndex->begin();
7993   int *arrInOutPtr=arrInOut->getPointer();
7994   const int *srcArrPtr=srcArr->begin();
7995   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7996     {
7997       if(*it>=0 && *it<nbOfTuples)
7998         {
7999           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8000             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8001           else
8002             {
8003               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] !";
8004               throw INTERP_KERNEL::Exception(oss.str());
8005             }
8006         }
8007       else
8008         {
8009           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8010           throw INTERP_KERNEL::Exception(oss.str());
8011         }
8012     }
8013 }
8014
8015 /*!
8016  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8017  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8018  * 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]].
8019  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8020  * A negative value in \b arrIn means that it is ignored.
8021  * 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.
8022  * 
8023  * \param [in] arrIn arr origin array from which the extraction will be done.
8024  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8025  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8026  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8027  */
8028 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8029 {
8030   int seed=0,nbOfDepthPeelingPerformed=0;
8031   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8032 }
8033
8034 /*!
8035  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8036  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8037  * 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]].
8038  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8039  * A negative value in \b arrIn means that it is ignored.
8040  * 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.
8041  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8042  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8043  * \param [in] arrIn arr origin array from which the extraction will be done.
8044  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8045  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8046  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8047  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8048  * \sa MEDCouplingUMesh::partitionBySpreadZone
8049  */
8050 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
8051 {
8052   nbOfDepthPeelingPerformed=0;
8053   if(!arrIndxIn)
8054     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8055   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8056   if(nbOfTuples<=0)
8057     {
8058       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8059       return ret;
8060     }
8061   //
8062   std::vector<bool> fetched(nbOfTuples,false);
8063   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8064 }
8065
8066
8067 /*!
8068  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8069  * 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
8070  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8071  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8072  *
8073  * \param [in] start begin of set of ids of the input extraction (included)
8074  * \param [in] end end of set of ids of the input extraction (excluded)
8075  * \param [in] step step of the set of ids in range mode.
8076  * \param [in] arrIn arr origin array from which the extraction will be done.
8077  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8078  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8079  * \param [in] srcArrIndex index array of \b srcArr
8080  * \param [out] arrOut the resulting array
8081  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8082  * 
8083  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8084  */
8085 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8086                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8087                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
8088 {
8089   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8090     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
8091   MCAuto<DataArrayInt> arro=DataArrayInt::New();
8092   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
8093   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8094   int offset=0;
8095   const int *arrIndxInPtr=arrIndxIn->begin();
8096   const int *srcArrIndexPtr=srcArrIndex->begin();
8097   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
8098   int it=start;
8099   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8100     {
8101       if(it>=0 && it<nbOfTuples)
8102         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8103       else
8104         {
8105           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8106           throw INTERP_KERNEL::Exception(oss.str());
8107         }
8108     }
8109   srcArrIndexPtr=srcArrIndex->begin();
8110   arrIo->alloc(nbOfTuples+1,1);
8111   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8112   const int *arrInPtr=arrIn->begin();
8113   const int *srcArrPtr=srcArr->begin();
8114   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8115   int *arroPtr=arro->getPointer();
8116   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8117     {
8118       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8119       if(pos<0)
8120         {
8121           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8122           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8123         }
8124       else
8125         {
8126           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8127           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8128         }
8129     }
8130   arrOut=arro.retn();
8131   arrIndexOut=arrIo.retn();
8132 }
8133
8134 /*!
8135  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8136  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8137  *
8138  * \param [in] start begin of set of ids of the input extraction (included)
8139  * \param [in] end end of set of ids of the input extraction (excluded)
8140  * \param [in] step step of the set of ids in range mode.
8141  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8142  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8143  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8144  * \param [in] srcArrIndex index array of \b srcArr
8145  * 
8146  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8147  */
8148 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8149                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
8150 {
8151   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8152     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
8153   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8154   const int *arrIndxInPtr=arrIndxIn->begin();
8155   const int *srcArrIndexPtr=srcArrIndex->begin();
8156   int *arrInOutPtr=arrInOut->getPointer();
8157   const int *srcArrPtr=srcArr->begin();
8158   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
8159   int it=start;
8160   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8161     {
8162       if(it>=0 && it<nbOfTuples)
8163         {
8164           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
8165             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
8166           else
8167             {
8168               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8169               throw INTERP_KERNEL::Exception(oss.str());
8170             }
8171         }
8172       else
8173         {
8174           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8175           throw INTERP_KERNEL::Exception(oss.str());
8176         }
8177     }
8178 }
8179
8180 /*!
8181  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8182  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8183  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8184  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8185  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8186  * 
8187  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8188  */
8189 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
8190 {
8191   checkFullyDefined();
8192   int mdim=getMeshDimension();
8193   int spaceDim=getSpaceDimension();
8194   if(mdim!=spaceDim)
8195     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8196   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8197   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8198   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
8199   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8200   ret->setCoords(getCoords());
8201   ret->allocateCells((int)partition.size());
8202   //
8203   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8204     {
8205       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8206       MCAuto<DataArrayInt> cell;
8207       switch(mdim)
8208       {
8209         case 2:
8210           cell=tmp->buildUnionOf2DMesh();
8211           break;
8212         case 3:
8213           cell=tmp->buildUnionOf3DMesh();
8214           break;
8215         default:
8216           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8217       }
8218
8219       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->begin()+1);
8220     }
8221   //
8222   ret->finishInsertingCells();
8223   return ret.retn();
8224 }
8225
8226 /*!
8227  * This method partitions \b this into contiguous zone.
8228  * This method only needs a well defined connectivity. Coordinates are not considered here.
8229  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8230  */
8231 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
8232 {
8233   DataArrayInt *neigh=0,*neighI=0;
8234   computeNeighborsOfCells(neigh,neighI);
8235   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8236   return PartitionBySpreadZone(neighAuto,neighIAuto);
8237 }
8238
8239 std::vector<DataArrayInt *> MEDCouplingUMesh::PartitionBySpreadZone(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8240 {
8241   if(!arrIn || !arrIndxIn)
8242     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : null input pointers !");
8243   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8244   int nbOfTuples(arrIndxIn->getNumberOfTuples());
8245   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1 || nbOfTuples<1)
8246     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : invalid arrays in input !");
8247   int nbOfCellsCur(nbOfTuples-1);
8248   std::vector<DataArrayInt *> ret;
8249   if(nbOfCellsCur<=0)
8250     return ret;
8251   std::vector<bool> fetchedCells(nbOfCellsCur,false);
8252   std::vector< MCAuto<DataArrayInt> > ret2;
8253   int seed=0;
8254   while(seed<nbOfCellsCur)
8255     {
8256       int nbOfPeelPerformed=0;
8257       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfPeelPerformed));
8258       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8259     }
8260   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8261     ret.push_back((*it).retn());
8262   return ret;
8263 }
8264
8265 /*!
8266  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8267  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8268  *
8269  * \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.
8270  * \return a newly allocated DataArrayInt to be managed by the caller.
8271  * \throw In case of \a code has not the right format (typically of size 3*n)
8272  */
8273 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
8274 {
8275   MCAuto<DataArrayInt> ret=DataArrayInt::New();
8276   std::size_t nb=code.size()/3;
8277   if(code.size()%3!=0)
8278     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8279   ret->alloc((int)nb,2);
8280   int *retPtr=ret->getPointer();
8281   for(std::size_t i=0;i<nb;i++,retPtr+=2)
8282     {
8283       retPtr[0]=code[3*i+2];
8284       retPtr[1]=code[3*i+2]+code[3*i+1];
8285     }
8286   return ret.retn();
8287 }
8288
8289 /*!
8290  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
8291  * All cells in \a this are expected to be linear 3D cells.
8292  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
8293  * It leads to an increase to number of cells.
8294  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
8295  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
8296  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
8297  *
8298  * \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.
8299  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
8300  * \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. 
8301  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
8302  *          an id of old cell producing it. The caller is to delete this array using
8303  *         decrRef() as it is no more needed.
8304  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
8305  *
8306  * \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
8307  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
8308  * 
8309  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
8310  * \throw If \a this is not fully constituted with linear 3D cells.
8311  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
8312  */
8313 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
8314 {
8315   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
8316   checkConnectivityFullyDefined();
8317   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8318     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
8319   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
8320   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
8321   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
8322   int *retPt(ret->getPointer());
8323   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
8324   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
8325   const int *oldc(_nodal_connec->begin());
8326   const int *oldci(_nodal_connec_index->begin());
8327   const double *coords(_coords->begin());
8328   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
8329     {
8330       std::vector<int> a; std::vector<double> b;
8331       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
8332       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
8333       const int *aa(&a[0]);
8334       if(!b.empty())
8335         {
8336           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
8337             if(*it<0)
8338               *it=(-(*(it))-1+nbNodes);
8339           addPts->insertAtTheEnd(b.begin(),b.end());
8340           nbNodes+=(int)b.size()/3;
8341         }
8342       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
8343         newConn->insertAtTheEnd(aa,aa+4);
8344     }
8345   if(!addPts->empty())
8346     {
8347       addPts->rearrange(3);
8348       nbOfAdditionalPoints=addPts->getNumberOfTuples();
8349       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
8350       ret0->setCoords(addPts);
8351     }
8352   else
8353     {
8354       nbOfAdditionalPoints=0;
8355       ret0->setCoords(getCoords());
8356     }
8357   ret0->setNodalConnectivity(newConn);
8358   //
8359   ret->computeOffsetsFull();
8360   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
8361   return ret0.retn();
8362 }
8363
8364 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8365     _own_cell(true),_cell_id(-1),_nb_cell(0)
8366 {
8367   if(mesh)
8368     {
8369       mesh->incrRef();
8370       _nb_cell=mesh->getNumberOfCells();
8371     }
8372 }
8373
8374 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8375 {
8376   if(_mesh)
8377     _mesh->decrRef();
8378   if(_own_cell)
8379     delete _cell;
8380 }
8381
8382 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8383     _own_cell(false),_cell_id(bg-1),
8384     _nb_cell(end)
8385 {
8386   if(mesh)
8387     mesh->incrRef();
8388 }
8389
8390 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8391 {
8392   _cell_id++;
8393   if(_cell_id<_nb_cell)
8394     {
8395       _cell->next();
8396       return _cell;
8397     }
8398   else
8399     return 0;
8400 }
8401
8402 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8403 {
8404   if(_mesh)
8405     _mesh->incrRef();
8406 }
8407
8408 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8409 {
8410   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8411 }
8412
8413 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8414 {
8415   if(_mesh)
8416     _mesh->decrRef();
8417 }
8418
8419 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8420     _itc(itc),
8421     _bg(bg),_end(end)
8422 {
8423   if(_mesh)
8424     _mesh->incrRef();
8425 }
8426
8427 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8428 {
8429   if(_mesh)
8430     _mesh->decrRef();
8431 }
8432
8433 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8434 {
8435   return _type;
8436 }
8437
8438 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8439 {
8440   return _end-_bg;
8441 }
8442
8443 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8444 {
8445   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8446 }
8447
8448 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8449 {
8450   if(mesh)
8451     {
8452       mesh->incrRef();
8453       _nb_cell=mesh->getNumberOfCells();
8454     }
8455 }
8456
8457 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8458 {
8459   if(_mesh)
8460     _mesh->decrRef();
8461   delete _cell;
8462 }
8463
8464 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8465 {
8466   const int *c=_mesh->getNodalConnectivity()->begin();
8467   const int *ci=_mesh->getNodalConnectivityIndex()->begin();
8468   if(_cell_id<_nb_cell)
8469     {
8470       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8471       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
8472       int startId=_cell_id;
8473       _cell_id+=nbOfElems;
8474       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8475     }
8476   else
8477     return 0;
8478 }
8479
8480 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8481 {
8482   if(mesh)
8483     {
8484       _conn=mesh->getNodalConnectivity()->getPointer();
8485       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8486     }
8487 }
8488
8489 void MEDCouplingUMeshCell::next()
8490 {
8491   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8492     {
8493       _conn+=_conn_lgth;
8494       _conn_indx++;
8495     }
8496   _conn_lgth=_conn_indx[1]-_conn_indx[0];
8497 }
8498
8499 std::string MEDCouplingUMeshCell::repr() const
8500 {
8501   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8502     {
8503       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8504       oss << " : ";
8505       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8506       return oss.str();
8507     }
8508   else
8509     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8510 }
8511
8512 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8513 {
8514   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8515     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8516   else
8517     return INTERP_KERNEL::NORM_ERROR;
8518 }
8519
8520 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8521 {
8522   lgth=_conn_lgth;
8523   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8524     return _conn;
8525   else
8526     return 0;
8527 }