Salome HOME
f90c9c49a0d31701708e23d5046d742c427eabe9
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMeshQuality.hxx"
34 #include "InterpKernelCellSimplify.hxx"
35 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
36 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const throw(INTERP_KERNEL::Exception)
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
120 {
121   std::size_t ret=0;
122   if(_nodal_connec)
123     ret+=_nodal_connec->getHeapMemorySize();
124   if(_nodal_connec_index)
125     ret+=_nodal_connec_index->getHeapMemorySize();
126   return MEDCouplingPointSet::getHeapMemorySize()+ret;
127 }
128
129 void MEDCouplingUMesh::updateTime() const
130 {
131   MEDCouplingPointSet::updateTime();
132   if(_nodal_connec)
133     {
134       updateTimeWith(*_nodal_connec);
135     }
136   if(_nodal_connec_index)
137     {
138       updateTimeWith(*_nodal_connec_index);
139     }
140 }
141
142 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
143 {
144 }
145
146 /*!
147  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
148  * then \a this mesh is most probably is writable, exchangeable and available for most
149  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
150  * this method to check that all is in order with \a this mesh.
151  *  \throw If the mesh dimension is not set.
152  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
153  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
154  *  \throw If the connectivity data array has more than one component.
155  *  \throw If the connectivity data array has a named component.
156  *  \throw If the connectivity index data array has more than one component.
157  *  \throw If the connectivity index data array has a named component.
158  */
159 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
160 {
161   if(_mesh_dim<-1)
162    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
163   if(_mesh_dim!=-1)
164     MEDCouplingPointSet::checkCoherency();
165   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
166     {
167       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
168         {
169           std::ostringstream message;
170           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
171           throw INTERP_KERNEL::Exception(message.str().c_str());
172         }
173     }
174   if(_nodal_connec)
175     {
176       if(_nodal_connec->getNumberOfComponents()!=1)
177         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
178       if(_nodal_connec->getInfoOnComponent(0)!="")
179         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
180     }
181   else
182     if(_mesh_dim!=-1)
183       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
184   if(_nodal_connec_index)
185     {
186       if(_nodal_connec_index->getNumberOfComponents()!=1)
187         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
188       if(_nodal_connec_index->getInfoOnComponent(0)!="")
189         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
190     }
191   else
192     if(_mesh_dim!=-1)
193       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
194 }
195
196 /*!
197  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
198  * then \a this mesh is most probably is writable, exchangeable and available for all
199  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
200  * method thoroughly checks the nodal connectivity.
201  *  \param [in] eps - a not used parameter.
202  *  \throw If the mesh dimension is not set.
203  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
204  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
205  *  \throw If the connectivity data array has more than one component.
206  *  \throw If the connectivity data array has a named component.
207  *  \throw If the connectivity index data array has more than one component.
208  *  \throw If the connectivity index data array has a named component.
209  *  \throw If number of nodes defining an element does not correspond to the type of element.
210  *  \throw If the nodal connectivity includes an invalid node id.
211  */
212 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
213 {
214   checkCoherency();
215   if(_mesh_dim==-1)
216     return ;
217   int meshDim=getMeshDimension();
218   int nbOfNodes=getNumberOfNodes();
219   int nbOfCells=getNumberOfCells();
220   const int *ptr=_nodal_connec->getConstPointer();
221   const int *ptrI=_nodal_connec_index->getConstPointer();
222   for(int i=0;i<nbOfCells;i++)
223     {
224       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
225       if((int)cm.getDimension()!=meshDim)
226         {
227           std::ostringstream oss;
228           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
229           throw INTERP_KERNEL::Exception(oss.str().c_str());
230         }
231       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
232       if(!cm.isDynamic())
233         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
234           {
235             std::ostringstream oss;
236             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
237             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
238             throw INTERP_KERNEL::Exception(oss.str().c_str());
239           }
240       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
241         {
242           int nodeId=*w;
243           if(nodeId>=0)
244             {
245               if(nodeId>=nbOfNodes)
246                 {
247                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
248                   throw INTERP_KERNEL::Exception(oss.str().c_str());
249                 }
250             }
251           else if(nodeId<-1)
252             {
253               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
254               throw INTERP_KERNEL::Exception(oss.str().c_str());
255             }
256           else
257             {
258               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
259                 {
260                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
261                   throw INTERP_KERNEL::Exception(oss.str().c_str());
262                 }
263             }
264         }
265     }
266 }
267
268
269 /*!
270  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
271  * then \a this mesh is most probably is writable, exchangeable and available for all
272  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
273  *  \param [in] eps - a not used parameter.
274  *  \throw If the mesh dimension is not set.
275  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
276  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
277  *  \throw If the connectivity data array has more than one component.
278  *  \throw If the connectivity data array has a named component.
279  *  \throw If the connectivity index data array has more than one component.
280  *  \throw If the connectivity index data array has a named component.
281  *  \throw If number of nodes defining an element does not correspond to the type of element.
282  *  \throw If the nodal connectivity includes an invalid node id.
283  */
284 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
285 {
286   checkCoherency1(eps);
287 }
288
289 /*!
290  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
291  * elements contained in the mesh. For more info on the mesh dimension see
292  * \ref MEDCouplingUMeshPage.
293  *  \param [in] meshDim - a new mesh dimension.
294  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
295  */
296 void MEDCouplingUMesh::setMeshDimension(int meshDim)
297 {
298   if(meshDim<-1 || meshDim>3)
299     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
300   _mesh_dim=meshDim;
301   declareAsNew();
302 }
303
304 /*!
305  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
306  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
307  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
308  *
309  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
310  *
311  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
312  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
313  */
314 void MEDCouplingUMesh::allocateCells(int nbOfCells)
315 {
316   if(nbOfCells<0)
317     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
318   if(_nodal_connec_index)
319     {
320       _nodal_connec_index->decrRef();
321     }
322   if(_nodal_connec)
323     {
324       _nodal_connec->decrRef();
325     }
326   _nodal_connec_index=DataArrayInt::New();
327   _nodal_connec_index->reserve(nbOfCells+1);
328   _nodal_connec_index->pushBackSilent(0);
329   _nodal_connec=DataArrayInt::New();
330   _nodal_connec->reserve(2*nbOfCells);
331   _types.clear();
332   declareAsNew();
333 }
334
335 /*!
336  * Appends a cell to the connectivity array. For deeper understanding what is
337  * happening see \ref MEDCouplingUMeshNodalConnectivity.
338  *  \param [in] type - type of cell to add.
339  *  \param [in] size - number of nodes constituting this cell.
340  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
341  * 
342  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
343  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
344  */
345 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
346 {
347   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
348   if(_nodal_connec_index==0)
349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
350   if((int)cm.getDimension()==_mesh_dim)
351     {
352       if(!cm.isDynamic())
353         if(size!=(int)cm.getNumberOfNodes())
354           {
355             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
356             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
357             throw INTERP_KERNEL::Exception(oss.str().c_str());
358           }
359       int idx=_nodal_connec_index->back();
360       int val=idx+size+1;
361       _nodal_connec_index->pushBackSilent(val);
362       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
363       _types.insert(type);
364     }
365   else
366     {
367       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
368       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
369       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
370       throw INTERP_KERNEL::Exception(oss.str().c_str());
371     }
372 }
373
374 /*!
375  * Compacts data arrays to release unused memory. This method is to be called after
376  * finishing cell insertion using \a this->insertNextCell().
377  * 
378  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
379  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
380  */
381 void MEDCouplingUMesh::finishInsertingCells()
382 {
383   _nodal_connec->pack();
384   _nodal_connec_index->pack();
385   _nodal_connec->declareAsNew();
386   _nodal_connec_index->declareAsNew();
387   updateTime();
388 }
389
390 /*!
391  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
392  * Useful for python users.
393  */
394 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
395 {
396   return new MEDCouplingUMeshCellIterator(this);
397 }
398
399 /*!
400  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
401  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
402  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
403  * Useful for python users.
404  */
405 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
406 {
407   if(!checkConsecutiveCellTypes())
408     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
409   return new MEDCouplingUMeshCellByTypeEntry(this);
410 }
411
412 /*!
413  * Returns a set of all cell types available in \a this mesh.
414  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
415  * \warning this method does not throw any exception even if \a this is not defined.
416  */
417 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
418 {
419   return _types;
420 }
421
422 /*!
423  * This method is a method that compares \a this and \a other.
424  * This method compares \b all attributes, even names and component names.
425  */
426 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
427 {
428   if(!other)
429     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
430   std::ostringstream oss; oss.precision(15);
431   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
432   if(!otherC)
433     {
434       reason="mesh given in input is not castable in MEDCouplingUMesh !";
435       return false;
436     }
437   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
438     return false;
439   if(_mesh_dim!=otherC->_mesh_dim)
440     {
441       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
442       reason=oss.str();
443       return false;
444     }
445   if(_types!=otherC->_types)
446     {
447       oss << "umesh geometric type mismatch :\nThis geometric types are :";
448       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
449         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
450       oss << "\nOther geometric types are :";
451       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
452         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
453       reason=oss.str();
454       return false;
455     }
456   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
457     if(_nodal_connec==0 || otherC->_nodal_connec==0)
458       {
459         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
460         return false;
461       }
462   if(_nodal_connec!=otherC->_nodal_connec)
463     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
464       {
465         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
466         return false;
467       }
468   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
469     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
470       {
471         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
472         return false;
473       }
474   if(_nodal_connec_index!=otherC->_nodal_connec_index)
475     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
476       {
477         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
478         return false;
479       }
480   return true;
481 }
482
483 /*!
484  * Checks if data arrays of this mesh (node coordinates, nodal
485  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
486  * not considered.
487  *  \param [in] other - the mesh to compare with.
488  *  \param [in] prec - precision value used to compare node coordinates.
489  *  \return bool - \a true if the two meshes are same.
490  */
491 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
492 {
493   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
494   if(!otherC)
495     return false;
496   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
497     return false;
498   if(_mesh_dim!=otherC->_mesh_dim)
499     return false;
500   if(_types!=otherC->_types)
501     return false;
502   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
503     if(_nodal_connec==0 || otherC->_nodal_connec==0)
504       return false;
505   if(_nodal_connec!=otherC->_nodal_connec)
506     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
507       return false;
508   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
509     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
510       return false;
511   if(_nodal_connec_index!=otherC->_nodal_connec_index)
512     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
513       return false;
514   return true;
515 }
516
517 /*!
518  * Checks if \a this and \a other meshes are geometrically equivalent with high
519  * probability, else an exception is thrown. The meshes are considered equivalent if
520  * (1) meshes contain the same number of nodes and the same number of elements of the
521  * same types (2) three cells of the two meshes (first, last and middle) are based
522  * on coincident nodes (with a specified precision).
523  *  \param [in] other - the mesh to compare with.
524  *  \param [in] prec - the precision used to compare nodes of the two meshes.
525  *  \throw If the two meshes do not match.
526  */
527 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
528 {
529  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
530  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
531   if(!otherC)
532     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
533 }
534
535 /*!
536  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
537  * cells each node belongs to.
538  * \warning For speed reasons, this method does not check if node ids in the nodal
539  *          connectivity correspond to the size of node coordinates array.
540  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
541  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
542  *        dividing cell ids in \a revNodal into groups each referring to one
543  *        node. Its every element (except the last one) is an index pointing to the
544  *         first id of a group of cells. For example cells sharing the node #1 are 
545  *        described by following range of indices: 
546  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
547  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
548  *        Number of cells sharing the *i*-th node is
549  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
550  * \throw If the coordinates array is not set.
551  * \throw If the nodal connectivity of cells is not defined.
552  * 
553  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
554  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
555  */
556 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
557 {
558   checkFullyDefined();
559   int nbOfNodes=getNumberOfNodes();
560   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
561   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
562   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
563   const int *conn=_nodal_connec->getConstPointer();
564   const int *connIndex=_nodal_connec_index->getConstPointer();
565   int nbOfCells=getNumberOfCells();
566   int nbOfEltsInRevNodal=0;
567   for(int eltId=0;eltId<nbOfCells;eltId++)
568     {
569       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
570       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
571       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
572         if(*iter>=0)//for polyhedrons
573           {
574             nbOfEltsInRevNodal++;
575             revNodalIndxPtr[(*iter)+1]++;
576           }
577     }
578   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
579   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
580   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
581   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
582   for(int eltId=0;eltId<nbOfCells;eltId++)
583     {
584       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
585       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
586       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
587         if(*iter>=0)//for polyhedrons
588           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
589     }
590 }
591
592 /// @cond INTERNAL
593
594 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
595 {
596   return id;
597 }
598
599 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
600 {
601   if(!compute)
602     return id+1;
603   else
604     {
605       if(cm.getOrientationStatus(nb,conn1,conn2))
606         return id+1;
607       else
608         return -(id+1);
609     }
610 }
611
612 class MinusOneSonsGenerator
613 {
614 public:
615   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
616   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
617   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
618   static const int DELTA=1;
619 private:
620   const INTERP_KERNEL::CellModel& _cm;
621 };
622
623 class MinusOneSonsGeneratorBiQuadratic
624 {
625 public:
626   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
627   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
628   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
629   static const int DELTA=1;
630 private:
631   const INTERP_KERNEL::CellModel& _cm;
632 };
633
634 class MinusTwoSonsGenerator
635 {
636 public:
637   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
638   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
639   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
640   static const int DELTA=2;
641 private:
642   const INTERP_KERNEL::CellModel& _cm;
643 };
644
645 /// @endcond
646
647 /*!
648  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
649  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
650  * describing correspondence between cells of \a this and the result meshes are
651  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
652  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
653  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
654  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
655  * \warning For speed reasons, this method does not check if node ids in the nodal
656  *          connectivity correspond to the size of node coordinates array.
657  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
658  *          to write this mesh to the MED file, its cells must be sorted using
659  *          sortCellsInMEDFileFrmt().
660  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
661  *         each cell of \a this mesh.
662  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
663  *        dividing cell ids in \a desc into groups each referring to one
664  *        cell of \a this mesh. Its every element (except the last one) is an index
665  *        pointing to the first id of a group of cells. For example cells of the
666  *        result mesh bounding the cell #1 of \a this mesh are described by following
667  *        range of indices:
668  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
669  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
670  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
671  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
672  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
673  *         by each cell of the result mesh.
674  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
675  *        in the result mesh,
676  *        dividing cell ids in \a revDesc into groups each referring to one
677  *        cell of the result mesh the same way as \a descIndx divides \a desc.
678  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
679  *        delete this mesh using decrRef() as it is no more needed.
680  *  \throw If the coordinates array is not set.
681  *  \throw If the nodal connectivity of cells is node defined.
682  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
683  *         revDescIndx == NULL.
684  * 
685  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
686  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
687  * \sa buildDescendingConnectivity2()
688  */
689 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
690 {
691   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
692 }
693
694 /*!
695  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
696  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
697  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
698  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
699  * \sa MEDCouplingUMesh::buildDescendingConnectivity
700  */
701 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
702 {
703   checkFullyDefined();
704   if(getMeshDimension()!=3)
705     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
706   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
707 }
708
709 /*!
710  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
711  * this->getMeshDimension(), that bound cells of \a this mesh. In
712  * addition arrays describing correspondence between cells of \a this and the result
713  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
714  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
715  *  mesh. This method differs from buildDescendingConnectivity() in that apart
716  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
717  * result meshes. So a positive id means that order of nodes in corresponding cells
718  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
719  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
720  * i.e. cell ids are one-based.
721  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
722  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
723  * \warning For speed reasons, this method does not check if node ids in the nodal
724  *          connectivity correspond to the size of node coordinates array.
725  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
726  *          to write this mesh to the MED file, its cells must be sorted using
727  *          sortCellsInMEDFileFrmt().
728  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
729  *         each cell of \a this mesh.
730  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
731  *        dividing cell ids in \a desc into groups each referring to one
732  *        cell of \a this mesh. Its every element (except the last one) is an index
733  *        pointing to the first id of a group of cells. For example cells of the
734  *        result mesh bounding the cell #1 of \a this mesh are described by following
735  *        range of indices:
736  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
737  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
738  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
739  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
740  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
741  *         by each cell of the result mesh.
742  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
743  *        in the result mesh,
744  *        dividing cell ids in \a revDesc into groups each referring to one
745  *        cell of the result mesh the same way as \a descIndx divides \a desc.
746  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
747  *        shares the node coordinates array with \a this mesh. The caller is to
748  *        delete this mesh using decrRef() as it is no more needed.
749  *  \throw If the coordinates array is not set.
750  *  \throw If the nodal connectivity of cells is node defined.
751  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
752  *         revDescIndx == NULL.
753  * 
754  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
755  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
756  * \sa buildDescendingConnectivity()
757  */
758 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
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 MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
766  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
767  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
768  *
769  * \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
770  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
771  * \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.
772  */
773 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
774 {
775   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
776   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
777   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
778   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
779   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
780   meshDM1=0;
781   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
782 }
783
784 /*!
785  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
786  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
787  * excluding a set of meshdim-1 cells in input descending connectivity.
788  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
789  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
790  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
791  *
792  * \param [in] desc descending connectivity array.
793  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
794  * \param [in] revDesc reverse descending connectivity array.
795  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
796  * \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
797  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
798  * \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.
799  */
800 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
801                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
802 {
803   if(!desc || !descIndx || !revDesc || !revDescIndx)
804     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
805   const int *descPtr=desc->getConstPointer();
806   const int *descIPtr=descIndx->getConstPointer();
807   const int *revDescPtr=revDesc->getConstPointer();
808   const int *revDescIPtr=revDescIndx->getConstPointer();
809   //
810   int nbCells=descIndx->getNumberOfTuples()-1;
811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
812   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
813   int *out1Ptr=out1->getPointer();
814   *out1Ptr++=0;
815   out0->reserve(desc->getNumberOfTuples());
816   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
817     {
818       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
819         {
820           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
821           s.erase(i);
822           out0->insertAtTheEnd(s.begin(),s.end());
823         }
824       *out1Ptr=out0->getNumberOfTuples();
825     }
826   neighbors=out0.retn();
827   neighborsIndx=out1.retn();
828 }
829
830 /// @cond INTERNAL
831
832 /*!
833  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
834  * For speed reasons no check of this will be done.
835  */
836 template<class SonsGenerator>
837 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
838 {
839   if(!desc || !descIndx || !revDesc || !revDescIndx)
840     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
841   checkConnectivityFullyDefined();
842   int nbOfCells=getNumberOfCells();
843   int nbOfNodes=getNumberOfNodes();
844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
845   int *revNodalIndxPtr=revNodalIndx->getPointer();
846   const int *conn=_nodal_connec->getConstPointer();
847   const int *connIndex=_nodal_connec_index->getConstPointer();
848   std::string name="Mesh constituent of "; name+=getName();
849   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
850   ret->setCoords(getCoords());
851   ret->allocateCells(2*nbOfCells);
852   descIndx->alloc(nbOfCells+1,1);
853   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
854   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
855   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
856     {
857       int pos=connIndex[eltId];
858       int posP1=connIndex[eltId+1];
859       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
860       SonsGenerator sg(cm);
861       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
862       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
863       for(unsigned i=0;i<nbOfSons;i++)
864         {
865           INTERP_KERNEL::NormalizedCellType cmsId;
866           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
867           for(unsigned k=0;k<nbOfNodesSon;k++)
868             if(tmp[k]>=0)
869               revNodalIndxPtr[tmp[k]+1]++;
870           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
871           revDesc2->pushBackSilent(eltId);
872         }
873       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
874     }
875   int nbOfCellsM1=ret->getNumberOfCells();
876   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
878   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
879   int *revNodalPtr=revNodal->getPointer();
880   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
881   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
882   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
883     {
884       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
885       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
886       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
887         if(*iter>=0)//for polyhedrons
888           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
889     }
890   //
891   DataArrayInt *commonCells=0,*commonCellsI=0;
892   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
893   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
894   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
895   int newNbOfCellsM1=-1;
896   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
897                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
898   std::vector<bool> isImpacted(nbOfCellsM1,false);
899   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
900     for(int work2=work[0];work2!=work[1];work2++)
901       isImpacted[commonCellsPtr[work2]]=true;
902   const int *o2nM1Ptr=o2nM1->getConstPointer();
903   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
904   const int *n2oM1Ptr=n2oM1->getConstPointer();
905   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
906   ret2->copyTinyInfoFrom(this);
907   desc->alloc(descIndx->back(),1);
908   int *descPtr=desc->getPointer();
909   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
910   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
911     {
912       if(!isImpacted[i])
913         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
914       else
915         {
916           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
917             {
918               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
919               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
920             }
921           else
922             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
923         }
924     }
925   revDesc->reserve(newNbOfCellsM1);
926   revDescIndx->alloc(newNbOfCellsM1+1,1);
927   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
928   const int *revDesc2Ptr=revDesc2->getConstPointer();
929   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
930     {
931       int oldCellIdM1=n2oM1Ptr[i];
932       if(!isImpacted[oldCellIdM1])
933         {
934           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
935           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
936         }
937       else
938         {
939           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
940             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
941           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
942           commonCellsIPtr++;
943         }
944     }
945   //
946   return ret2.retn();
947 }
948
949 struct MEDCouplingAccVisit
950 {
951   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
952   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
953   int _new_nb_of_nodes;
954 };
955
956 /// @endcond
957
958 /*!
959  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
960  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
961  * array of cell ids. Pay attention that after conversion all algorithms work slower
962  * with \a this mesh than before conversion. <br> If an exception is thrown during the
963  * conversion due presence of invalid ids in the array of cells to convert, as a
964  * result \a this mesh contains some already converted elements. In this case the 2D
965  * mesh remains valid but 3D mesh becomes \b inconsistent!
966  *  \warning This method can significantly modify the order of geometric types in \a this,
967  *          hence, to write this mesh to the MED file, its cells must be sorted using
968  *          sortCellsInMEDFileFrmt().
969  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
970  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
971  *         cellIdsToConvertBg.
972  *  \throw If the coordinates array is not set.
973  *  \throw If the nodal connectivity of cells is node defined.
974  *  \throw If dimension of \a this mesh is not either 2 or 3.
975  *
976  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
977  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
978  */
979 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
980 {
981   checkFullyDefined();
982   int dim=getMeshDimension();
983   if(dim<2 || dim>3)
984     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
985   int nbOfCells=getNumberOfCells();
986   if(dim==2)
987     {
988       const int *connIndex=_nodal_connec_index->getConstPointer();
989       int *conn=_nodal_connec->getPointer();
990       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
991         {
992           if(*iter>=0 && *iter<nbOfCells)
993             {
994               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
995               if(!cm.isQuadratic())
996                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
997               else
998                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
999             }
1000           else
1001             {
1002               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1003               oss << " in range [0," << nbOfCells << ") !";
1004               throw INTERP_KERNEL::Exception(oss.str().c_str());
1005             }
1006         }
1007     }
1008   else
1009     {
1010       int *connIndex=_nodal_connec_index->getPointer();
1011       int connIndexLgth=_nodal_connec_index->getNbOfElems();
1012       const int *connOld=_nodal_connec->getConstPointer();
1013       int connOldLgth=_nodal_connec->getNbOfElems();
1014       std::vector<int> connNew(connOld,connOld+connOldLgth);
1015       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1016         {
1017           if(*iter>=0 && *iter<nbOfCells)
1018             {
1019               int pos=connIndex[*iter];
1020               int posP1=connIndex[(*iter)+1];
1021               int lgthOld=posP1-pos-1;
1022               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1023               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1024               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1025               int *tmp=new int[nbOfFaces*lgthOld];
1026               int *work=tmp;
1027               for(int j=0;j<(int)nbOfFaces;j++)
1028                 {
1029                   INTERP_KERNEL::NormalizedCellType type;
1030                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1031                   work+=offset;
1032                   *work++=-1;
1033                 }
1034               std::size_t newLgth=std::distance(tmp,work)-1;
1035               std::size_t delta=newLgth-lgthOld;
1036               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1037               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1038               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1039               delete [] tmp;
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().c_str());
1046             }
1047         }
1048       _nodal_connec->alloc((int)connNew.size(),1);
1049       int *newConnPtr=_nodal_connec->getPointer();
1050       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1051     }
1052   computeTypes();
1053 }
1054
1055 /*!
1056  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1057  * polyhedrons (if \a this is a 3D mesh).
1058  *  \warning As this method is purely for user-friendliness and no optimization is
1059  *          done to avoid construction of a useless vector, this method can be costly
1060  *          in memory.
1061  *  \throw If the coordinates array is not set.
1062  *  \throw If the nodal connectivity of cells is node defined.
1063  *  \throw If dimension of \a this mesh is not either 2 or 3.
1064  */
1065 void MEDCouplingUMesh::convertAllToPoly()
1066 {
1067   int nbOfCells=getNumberOfCells();
1068   std::vector<int> cellIds(nbOfCells);
1069   for(int i=0;i<nbOfCells;i++)
1070     cellIds[i]=i;
1071   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1072 }
1073
1074 /*!
1075  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1076  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1077  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1078  * base facet of the volume and the second half of nodes describes an opposite facet
1079  * having the same number of nodes as the base one. This method converts such
1080  * connectivity to a valid polyhedral format where connectivity of each facet is
1081  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1082  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1083  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1084  * a correct orientation of the first facet of a polyhedron, else orientation of a
1085  * corrected cell is reverse.<br>
1086  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1087  * it releases the user from boring description of polyhedra connectivity in the valid
1088  * format.
1089  *  \throw If \a this->getMeshDimension() != 3.
1090  *  \throw If \a this->getSpaceDimension() != 3.
1091  *  \throw If the nodal connectivity of cells is not defined.
1092  *  \throw If the coordinates array is not set.
1093  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1094  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1095  *
1096  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1097  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1098  */
1099 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1100 {
1101   checkFullyDefined();
1102   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1103     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1104   int nbOfCells=getNumberOfCells();
1105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1106   newCi->alloc(nbOfCells+1,1);
1107   int *newci=newCi->getPointer();
1108   const int *ci=_nodal_connec_index->getConstPointer();
1109   const int *c=_nodal_connec->getConstPointer();
1110   newci[0]=0;
1111   for(int i=0;i<nbOfCells;i++)
1112     {
1113       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1114       if(type==INTERP_KERNEL::NORM_POLYHED)
1115         {
1116           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1117             {
1118               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1119               throw INTERP_KERNEL::Exception(oss.str().c_str());
1120             }
1121           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1122           if(n2%2!=0)
1123             {
1124               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 !";
1125               throw INTERP_KERNEL::Exception(oss.str().c_str());
1126             }
1127           int n1=(int)(n2/2);
1128           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)
1129         }
1130       else
1131         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1132     }
1133   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1134   newC->alloc(newci[nbOfCells],1);
1135   int *newc=newC->getPointer();
1136   for(int i=0;i<nbOfCells;i++)
1137     {
1138       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1139       if(type==INTERP_KERNEL::NORM_POLYHED)
1140         {
1141           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1142           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1143           *newc++=-1;
1144           for(std::size_t j=0;j<n1;j++)
1145             {
1146               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1147               newc[n1+5*j]=-1;
1148               newc[n1+5*j+1]=c[ci[i]+1+j];
1149               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1150               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1151               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1152             }
1153           newc+=n1*6;
1154         }
1155       else
1156         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1157     }
1158   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1159   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1160 }
1161
1162
1163 /*!
1164  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1165  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1166  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1167  *          to write this mesh to the MED file, its cells must be sorted using
1168  *          sortCellsInMEDFileFrmt().
1169  * \return \c true if at least one cell has been converted, \c false else. In the
1170  *         last case the nodal connectivity remains unchanged.
1171  * \throw If the coordinates array is not set.
1172  * \throw If the nodal connectivity of cells is not defined.
1173  * \throw If \a this->getMeshDimension() < 0.
1174  */
1175 bool MEDCouplingUMesh::unPolyze()
1176 {
1177   checkFullyDefined();
1178   int mdim=getMeshDimension();
1179   if(mdim<0)
1180     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1181   if(mdim<=1)
1182     return false;
1183   int nbOfCells=getNumberOfCells();
1184   if(nbOfCells<1)
1185     return false;
1186   int initMeshLgth=getMeshLength();
1187   int *conn=_nodal_connec->getPointer();
1188   int *index=_nodal_connec_index->getPointer();
1189   int posOfCurCell=0;
1190   int newPos=0;
1191   int lgthOfCurCell;
1192   bool ret=false;
1193   for(int i=0;i<nbOfCells;i++)
1194     {
1195       lgthOfCurCell=index[i+1]-posOfCurCell;
1196       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1197       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1198       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1199       int newLgth;
1200       if(cm.isDynamic())
1201         {
1202           switch(cm.getDimension())
1203             {
1204             case 2:
1205               {
1206                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1207                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1208                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1209                 break;
1210               }
1211             case 3:
1212               {
1213                 int nbOfFaces,lgthOfPolyhConn;
1214                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1215                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1216                 break;
1217               }
1218             case 1:
1219               {
1220                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1221                 break;
1222               }
1223             }
1224           ret=ret || (newType!=type);
1225           conn[newPos]=newType;
1226           newPos+=newLgth+1;
1227           posOfCurCell=index[i+1];
1228           index[i+1]=newPos;
1229         }
1230       else
1231         {
1232           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1233           newPos+=lgthOfCurCell;
1234           posOfCurCell+=lgthOfCurCell;
1235           index[i+1]=newPos;
1236         }
1237     }
1238   if(newPos!=initMeshLgth)
1239     _nodal_connec->reAlloc(newPos);
1240   if(ret)
1241     computeTypes();
1242   return ret;
1243 }
1244
1245 /*!
1246  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1247  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1248  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1249  *
1250  * \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 
1251  *             precision.
1252  */
1253 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1254 {
1255   checkFullyDefined();
1256   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1257     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1258   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1259   coords->recenterForMaxPrecision(eps);
1260   //
1261   int nbOfCells=getNumberOfCells();
1262   const int *conn=_nodal_connec->getConstPointer();
1263   const int *index=_nodal_connec_index->getConstPointer();
1264   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1265   connINew->alloc(nbOfCells+1,1);
1266   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1267   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1268   bool changed=false;
1269   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1270     {
1271       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1272         {
1273           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1274           changed=true;
1275         }
1276       else
1277         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1278       *connINewPtr=connNew->getNumberOfTuples();
1279     }
1280   if(changed)
1281     setConnectivity(connNew,connINew,false);
1282 }
1283
1284 /*!
1285  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1286  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1287  * the format of returned DataArrayInt instance.
1288  * 
1289  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1290  * \sa MEDCouplingUMesh::getNodeIdsInUse
1291  */
1292 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1293 {
1294   checkConnectivityFullyDefined();
1295   int nbOfCells=getNumberOfCells();
1296   const int *connIndex=_nodal_connec_index->getConstPointer();
1297   const int *conn=_nodal_connec->getConstPointer();
1298   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1299   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1300   std::vector<bool> retS(maxElt,false);
1301   for(int i=0;i<nbOfCells;i++)
1302     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1303       if(conn[j]>=0)
1304         retS[conn[j]]=true;
1305   int sz=0;
1306   for(int i=0;i<maxElt;i++)
1307     if(retS[i])
1308       sz++;
1309   DataArrayInt *ret=DataArrayInt::New();
1310   ret->alloc(sz,1);
1311   int *retPtr=ret->getPointer();
1312   for(int i=0;i<maxElt;i++)
1313     if(retS[i])
1314       *retPtr++=i;
1315   return ret;
1316 }
1317
1318 /*!
1319  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1320  * \sa MEDCouplingUMesh::getNodeIdsInUse
1321  */
1322 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1323 {
1324   int nbOfNodes=(int)nodeIdsInUse.size();
1325   int nbOfCells=getNumberOfCells();
1326   const int *connIndex=_nodal_connec_index->getConstPointer();
1327   const int *conn=_nodal_connec->getConstPointer();
1328   for(int i=0;i<nbOfCells;i++)
1329     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1330       if(conn[j]>=0)
1331         {
1332           if(conn[j]<nbOfNodes)
1333             nodeIdsInUse[conn[j]]=true;
1334           else
1335             {
1336               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1337               throw INTERP_KERNEL::Exception(oss.str().c_str());
1338             }
1339         }
1340 }
1341
1342 /*!
1343  * Finds nodes not used in any cell and returns an array giving a new id to every node
1344  * by excluding the unused nodes, for which the array holds -1. The result array is
1345  * a mapping in "Old to New" mode. 
1346  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1347  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1348  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1349  *          if the node is unused or a new id else. The caller is to delete this
1350  *          array using decrRef() as it is no more needed.  
1351  *  \throw If the coordinates array is not set.
1352  *  \throw If the nodal connectivity of cells is not defined.
1353  *  \throw If the nodal connectivity includes an invalid id.
1354  *
1355  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1356  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1357  * \sa computeNodeIdsAlg()
1358  */
1359 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1360 {
1361   nbrOfNodesInUse=-1;
1362   int nbOfNodes=getNumberOfNodes();
1363   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1364   ret->alloc(nbOfNodes,1);
1365   int *traducer=ret->getPointer();
1366   std::fill(traducer,traducer+nbOfNodes,-1);
1367   int nbOfCells=getNumberOfCells();
1368   const int *connIndex=_nodal_connec_index->getConstPointer();
1369   const int *conn=_nodal_connec->getConstPointer();
1370   for(int i=0;i<nbOfCells;i++)
1371     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1372       if(conn[j]>=0)
1373         {
1374           if(conn[j]<nbOfNodes)
1375             traducer[conn[j]]=1;
1376           else
1377             {
1378               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1379               throw INTERP_KERNEL::Exception(oss.str().c_str());
1380             }
1381         }
1382   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1383   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1384   return ret.retn();
1385 }
1386
1387 /*!
1388  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1389  * For each cell in \b this the number of nodes constituting cell is computed.
1390  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1391  * So for pohyhedrons some nodes can be counted several times in the returned result.
1392  * 
1393  * \return a newly allocated array
1394  */
1395 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1396 {
1397   checkConnectivityFullyDefined();
1398   int nbOfCells=getNumberOfCells();
1399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1400   ret->alloc(nbOfCells,1);
1401   int *retPtr=ret->getPointer();
1402   const int *conn=getNodalConnectivity()->getConstPointer();
1403   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1404   for(int i=0;i<nbOfCells;i++,retPtr++)
1405     {
1406       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1407         *retPtr=connI[i+1]-connI[i]-1;
1408       else
1409         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1410     }
1411   return ret.retn();
1412 }
1413
1414 /*!
1415  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1416  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1417  * 
1418  * \return a newly allocated array
1419  */
1420 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1421 {
1422   checkConnectivityFullyDefined();
1423   int nbOfCells=getNumberOfCells();
1424   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1425   ret->alloc(nbOfCells,1);
1426   int *retPtr=ret->getPointer();
1427   const int *conn=getNodalConnectivity()->getConstPointer();
1428   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1429   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1430     {
1431       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1432       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1433     }
1434   return ret.retn();
1435 }
1436
1437 /*!
1438  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1439  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1440  * array mean that the corresponding old node is no more used. 
1441  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1442  *           this->getNumberOfNodes() before call of this method. The caller is to
1443  *           delete this array using decrRef() as it is no more needed. 
1444  *  \throw If the coordinates array is not set.
1445  *  \throw If the nodal connectivity of cells is not defined.
1446  *  \throw If the nodal connectivity includes an invalid id.
1447  *
1448  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1449  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1450  */
1451 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1452 {
1453   return MEDCouplingPointSet::zipCoordsTraducer();
1454 }
1455
1456 /*!
1457  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1458  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1459  */
1460 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1461 {
1462   switch(compType)
1463     {
1464     case 0:
1465       return AreCellsEqual0(conn,connI,cell1,cell2);
1466     case 1:
1467       return AreCellsEqual1(conn,connI,cell1,cell2);
1468     case 2:
1469       return AreCellsEqual2(conn,connI,cell1,cell2);
1470     case 3:
1471       return AreCellsEqual3(conn,connI,cell1,cell2);
1472     case 7:
1473       return AreCellsEqual7(conn,connI,cell1,cell2);
1474     }
1475   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1476 }
1477
1478 /*!
1479  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1480  */
1481 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1482 {
1483   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1484     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1485   return 0;
1486 }
1487
1488 /*!
1489  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1490  */
1491 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1492 {
1493   int sz=connI[cell1+1]-connI[cell1];
1494   if(sz==connI[cell2+1]-connI[cell2])
1495     {
1496       if(conn[connI[cell1]]==conn[connI[cell2]])
1497         {
1498           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1499           unsigned dim=cm.getDimension();
1500           if(dim!=3)
1501             {
1502               if(dim!=1)
1503                 {
1504                   int sz1=2*(sz-1);
1505                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1506                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1507                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1508                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1509                   return work!=tmp+sz1?1:0;
1510                 }
1511               else
1512                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1513             }
1514           else
1515             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1516         }
1517     }
1518   return 0;
1519 }
1520
1521 /*!
1522  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1523  */
1524 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1525 {
1526   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1527     {
1528       if(conn[connI[cell1]]==conn[connI[cell2]])
1529         {
1530           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1531           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1532           return s1==s2?1:0;
1533         }
1534     }
1535   return 0;
1536 }
1537
1538 /*!
1539  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1540  */
1541 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1542 {
1543   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1544     {
1545       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1546       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1547       return s1==s2?1:0;
1548     }
1549   return 0;
1550 }
1551
1552 /*!
1553  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1554  */
1555 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1556 {
1557   int sz=connI[cell1+1]-connI[cell1];
1558   if(sz==connI[cell2+1]-connI[cell2])
1559     {
1560       if(conn[connI[cell1]]==conn[connI[cell2]])
1561         {
1562           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1563           unsigned dim=cm.getDimension();
1564           if(dim!=3)
1565             {
1566               if(dim!=1)
1567                 {
1568                   int sz1=2*(sz-1);
1569                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1570                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1571                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1572                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1573                   if(work!=tmp+sz1)
1574                     return 1;
1575                   else
1576                     {
1577                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1578                       std::reverse_iterator<int *> it2((int *)tmp);
1579                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1580                         return 2;
1581                       else
1582                         return 0;
1583                     }
1584                   
1585                   return work!=tmp+sz1?1:0;
1586                 }
1587               else
1588                 {//case of SEG2 and SEG3
1589                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1590                     return 1;
1591                   if(!cm.isQuadratic())
1592                     {
1593                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1594                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1595                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1596                         return 2;
1597                       return 0;
1598                     }
1599                   else
1600                     {
1601                       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])
1602                         return 2;
1603                       return 0;
1604                     }
1605                 }
1606             }
1607           else
1608             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1609         }
1610     }
1611   return 0;
1612 }
1613
1614 /*!
1615  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1616  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1617  * and result remains unchanged.
1618  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1619  * If in 'candidates' pool -1 value is considered as an empty value.
1620  * WARNING this method returns only ONE set of result !
1621  */
1622 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1623 {
1624   if(candidates.size()<1)
1625     return false;
1626   bool ret=false;
1627   std::vector<int>::const_iterator iter=candidates.begin();
1628   int start=(*iter++);
1629   for(;iter!=candidates.end();iter++)
1630     {
1631       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1632       if(status!=0)
1633         {
1634           if(!ret)
1635             {
1636               result->pushBackSilent(start);
1637               ret=true;
1638             }
1639           if(status==1)
1640             result->pushBackSilent(*iter);
1641           else
1642             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1643         }
1644     }
1645   return ret;
1646 }
1647
1648 /*!
1649  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1650  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1651  *
1652  * \param [in] compType input specifying the technique used to compare cells each other.
1653  *   - 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.
1654  *   - 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)
1655  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1656  *   - 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
1657  * can be used for users not sensitive to orientation of cell
1658  * \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.
1659  * \param [out] commonCells
1660  * \param [out] commonCellsI
1661  * \return the correspondance array old to new in a newly allocated array.
1662  * 
1663  */
1664 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1665 {
1666   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1667   getReverseNodalConnectivity(revNodal,revNodalI);
1668   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1669 }
1670
1671 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1672                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1673 {
1674   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1675   int nbOfCells=nodalI->getNumberOfTuples()-1;
1676   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1677   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1678   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1679   std::vector<bool> isFetched(nbOfCells,false);
1680   if(startCellId==0)
1681     {
1682       for(int i=0;i<nbOfCells;i++)
1683         {
1684           if(!isFetched[i])
1685             {
1686               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1687               std::vector<int> v,v2;
1688               if(connOfNode!=connPtr+connIPtr[i+1])
1689                 {
1690                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1691                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1692                   connOfNode++;
1693                 }
1694               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1695                 if(*connOfNode>=0)
1696                   {
1697                     v=v2;
1698                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1699                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1700                     v2.resize(std::distance(v2.begin(),it));
1701                   }
1702               if(v2.size()>1)
1703                 {
1704                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1705                     {
1706                       int pos=commonCellsI->back();
1707                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1708                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1709                         isFetched[*it]=true;
1710                     }
1711                 }
1712             }
1713         }
1714     }
1715   else
1716     {
1717       for(int i=startCellId;i<nbOfCells;i++)
1718         {
1719           if(!isFetched[i])
1720             {
1721               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1722               std::vector<int> v,v2;
1723               if(connOfNode!=connPtr+connIPtr[i+1])
1724                 {
1725                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1726                   connOfNode++;
1727                 }
1728               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1729                 if(*connOfNode>=0)
1730                   {
1731                     v=v2;
1732                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1733                     v2.resize(std::distance(v2.begin(),it));
1734                   }
1735               if(v2.size()>1)
1736                 {
1737                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1738                     {
1739                       int pos=commonCellsI->back();
1740                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1741                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1742                         isFetched[*it]=true;
1743                     }
1744                 }
1745             }
1746         }
1747     }
1748   commonCellsArr=commonCells.retn();
1749   commonCellsIArr=commonCellsI.retn();
1750 }
1751
1752 /*!
1753  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1754  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1755  * than \a other->getNumberOfCells() in the returned array means that there is no
1756  * corresponding cell in \a this mesh.
1757  * It is expected that \a this and \a other meshes share the same node coordinates
1758  * array, if it is not so an exception is thrown. 
1759  *  \param [in] other - the mesh to compare with.
1760  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1761  *         valid values [0,1,2], see zipConnectivityTraducer().
1762  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1763  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1764  *         values. The caller is to delete this array using
1765  *         decrRef() as it is no more needed.
1766  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1767  *         mesh.
1768  *
1769  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1770  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1771  *  \sa checkDeepEquivalOnSameNodesWith()
1772  *  \sa checkGeoEquivalWith()
1773  */
1774 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1775 {
1776   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1777   int nbOfCells=getNumberOfCells();
1778   static const int possibleCompType[]={0,1,2};
1779   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1780     {
1781       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1782       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1783       oss << " !";
1784       throw INTERP_KERNEL::Exception(oss.str().c_str());
1785     }
1786   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1787   arr=o2n->substr(nbOfCells);
1788   arr->setName(other->getName());
1789   int tmp;
1790   if(other->getNumberOfCells()==0)
1791     return true;
1792   return arr->getMaxValue(tmp)<nbOfCells;
1793 }
1794
1795 /*!
1796  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1797  * This method tries to determine if \b other is fully included in \b this.
1798  * The main difference is that this method is not expected to throw exception.
1799  * This method has two outputs :
1800  *
1801  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1802  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1803  */
1804 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1805 {
1806   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1807   DataArrayInt *commonCells=0,*commonCellsI=0;
1808   int thisNbCells=getNumberOfCells();
1809   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1811   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1812   int otherNbCells=other->getNumberOfCells();
1813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1814   arr2->alloc(otherNbCells,1);
1815   arr2->fillWithZero();
1816   int *arr2Ptr=arr2->getPointer();
1817   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1818   for(int i=0;i<nbOfCommon;i++)
1819     {
1820       int start=commonCellsPtr[commonCellsIPtr[i]];
1821       if(start<thisNbCells)
1822         {
1823           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1824             {
1825               int sig=commonCellsPtr[j]>0?1:-1;
1826               int val=std::abs(commonCellsPtr[j])-1;
1827               if(val>=thisNbCells)
1828                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1829             }
1830         }
1831     }
1832   arr2->setName(other->getName());
1833   if(arr2->presenceOfValue(0))
1834     return false;
1835   arr=arr2.retn();
1836   return true;
1837 }
1838
1839 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1840 {
1841   if(!other)
1842     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1843   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1844   if(!otherC)
1845     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1846   std::vector<const MEDCouplingUMesh *> ms(2);
1847   ms[0]=this;
1848   ms[1]=otherC;
1849   return MergeUMeshesOnSameCoords(ms);
1850 }
1851
1852 /*!
1853  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1854  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1855  * cellIds is not given explicitely but by a range python like.
1856  * 
1857  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1858  * \return a newly allocated
1859  * 
1860  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1861  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1862  */
1863 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1864 {
1865   if(getMeshDimension()!=-1)
1866     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1867   else
1868     {
1869       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1870       if(newNbOfCells!=1)
1871         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1872       if(start!=0)
1873         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1874       incrRef();
1875       return const_cast<MEDCouplingUMesh *>(this);
1876     }
1877 }
1878
1879 /*!
1880  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1881  * The result mesh shares or not the node coordinates array with \a this mesh depending
1882  * on \a keepCoords parameter.
1883  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1884  *           to write this mesh to the MED file, its cells must be sorted using
1885  *           sortCellsInMEDFileFrmt().
1886  *  \param [in] begin - an array of cell ids to include to the new mesh.
1887  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1888  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1889  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1890  *         by calling zipCoords().
1891  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1892  *         to delete this mesh using decrRef() as it is no more needed. 
1893  *  \throw If the coordinates array is not set.
1894  *  \throw If the nodal connectivity of cells is not defined.
1895  *  \throw If any cell id in the array \a begin is not valid.
1896  *
1897  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1898  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1899  */
1900 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1901 {
1902   if(getMeshDimension()!=-1)
1903     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1904   else
1905     {
1906       if(end-begin!=1)
1907         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1908       if(begin[0]!=0)
1909         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1910       incrRef();
1911       return const_cast<MEDCouplingUMesh *>(this);
1912     }
1913 }
1914
1915 /*!
1916  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1917  *
1918  * 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.
1919  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1920  * The number of cells of \b this will remain the same with this method.
1921  *
1922  * \param [in] begin begin of cell ids (included) of cells in this to assign
1923  * \param [in] end end of cell ids (excluded) of cells in this to assign
1924  * \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 ).
1925  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1926  */
1927 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1928 {
1929   checkConnectivityFullyDefined();
1930   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1931   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1932     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1933   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1934     {
1935       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1936       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1937       throw INTERP_KERNEL::Exception(oss.str().c_str());
1938     }
1939   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1940   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1941     {
1942       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1943       throw INTERP_KERNEL::Exception(oss.str().c_str());
1944     }
1945   int nbOfCells=getNumberOfCells();
1946   bool easyAssign=true;
1947   const int *connI=_nodal_connec_index->getConstPointer();
1948   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1949   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1950     {
1951       if(*it>=0 && *it<nbOfCells)
1952         {
1953           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1954         }
1955       else
1956         {
1957           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1958           throw INTERP_KERNEL::Exception(oss.str().c_str());
1959         }
1960     }
1961   if(easyAssign)
1962     {
1963       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1964       computeTypes();
1965     }
1966   else
1967     {
1968       DataArrayInt *arrOut=0,*arrIOut=0;
1969       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1970                                                arrOut,arrIOut);
1971       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1972       setConnectivity(arrOut,arrIOut,true);
1973     }
1974 }
1975
1976 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1977 {
1978   checkConnectivityFullyDefined();
1979   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1980   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1982   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1983     {
1984       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1985       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1986       throw INTERP_KERNEL::Exception(oss.str().c_str());
1987     }
1988   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
1989   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1990     {
1991       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1992       throw INTERP_KERNEL::Exception(oss.str().c_str());
1993     }
1994   int nbOfCells=getNumberOfCells();
1995   bool easyAssign=true;
1996   const int *connI=_nodal_connec_index->getConstPointer();
1997   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1998   int it=start;
1999   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2000     {
2001       if(it>=0 && it<nbOfCells)
2002         {
2003           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2004         }
2005       else
2006         {
2007           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2008           throw INTERP_KERNEL::Exception(oss.str().c_str());
2009         }
2010     }
2011   if(easyAssign)
2012     {
2013       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2014       computeTypes();
2015     }
2016   else
2017     {
2018       DataArrayInt *arrOut=0,*arrIOut=0;
2019       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2020                                                 arrOut,arrIOut);
2021       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2022       setConnectivity(arrOut,arrIOut,true);
2023     }
2024 }                      
2025
2026 /*!
2027  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2028  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2029  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2030  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2031  *
2032  * \param [in] begin input start of array of node ids.
2033  * \param [in] end input end of array of node ids.
2034  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2035  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2036  */
2037 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2038 {
2039   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2040   checkConnectivityFullyDefined();
2041   int tmp=-1;
2042   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2043   std::vector<bool> fastFinder(sz,false);
2044   for(const int *work=begin;work!=end;work++)
2045     if(*work>=0 && *work<sz)
2046       fastFinder[*work]=true;
2047   int nbOfCells=getNumberOfCells();
2048   const int *conn=getNodalConnectivity()->getConstPointer();
2049   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2050   for(int i=0;i<nbOfCells;i++)
2051     {
2052       int ref=0,nbOfHit=0;
2053       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2054         if(*work2>=0)
2055           {
2056             ref++;
2057             if(fastFinder[*work2])
2058               nbOfHit++;
2059           }
2060       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2061         cellIdsKept->pushBackSilent(i);
2062     }
2063   cellIdsKeptArr=cellIdsKept.retn();
2064 }
2065
2066 /*!
2067  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2068  * this->getMeshDimension(), that bound some cells of \a this mesh.
2069  * The cells of lower dimension to include to the result mesh are selected basing on
2070  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2071  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2072  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2073  * created mesh shares the node coordinates array with \a this mesh. 
2074  *  \param [in] begin - the array of node ids.
2075  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2076  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2077  *         array \a begin are added, else cells whose any node is in the
2078  *         array \a begin are added.
2079  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2080  *         to delete this mesh using decrRef() as it is no more needed. 
2081  *  \throw If the coordinates array is not set.
2082  *  \throw If the nodal connectivity of cells is not defined.
2083  *  \throw If any node id in \a begin is not valid.
2084  *
2085  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2086  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2087  */
2088 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2089 {
2090   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2091   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2092   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2093   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2094   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2095 }
2096
2097 /*!
2098  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2099  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2100  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2101  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2102  *         by calling zipCoords().
2103  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2104  *         to delete this mesh using decrRef() as it is no more needed. 
2105  *  \throw If the coordinates array is not set.
2106  *  \throw If the nodal connectivity of cells is not defined.
2107  *
2108  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2109  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2110  */
2111 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2112 {
2113   DataArrayInt *desc=DataArrayInt::New();
2114   DataArrayInt *descIndx=DataArrayInt::New();
2115   DataArrayInt *revDesc=DataArrayInt::New();
2116   DataArrayInt *revDescIndx=DataArrayInt::New();
2117   //
2118   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2119   revDesc->decrRef();
2120   desc->decrRef();
2121   descIndx->decrRef();
2122   int nbOfCells=meshDM1->getNumberOfCells();
2123   const int *revDescIndxC=revDescIndx->getConstPointer();
2124   std::vector<int> boundaryCells;
2125   for(int i=0;i<nbOfCells;i++)
2126     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2127       boundaryCells.push_back(i);
2128   revDescIndx->decrRef();
2129   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2130   return ret;
2131 }
2132
2133 /*!
2134  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2135  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2136  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2137  */
2138 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2139 {
2140   checkFullyDefined();
2141   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2142   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2143   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2144   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2145   //
2146   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2147   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2148   //
2149   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2150   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2151   const int *revDescPtr=revDesc->getConstPointer();
2152   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2153   int nbOfCells=getNumberOfCells();
2154   std::vector<bool> ret1(nbOfCells,false);
2155   int sz=0;
2156   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2157     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2158       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2159   //
2160   DataArrayInt *ret2=DataArrayInt::New();
2161   ret2->alloc(sz,1);
2162   int *ret2Ptr=ret2->getPointer();
2163   sz=0;
2164   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2165     if(*it)
2166       *ret2Ptr++=sz;
2167   ret2->setName("BoundaryCells");
2168   return ret2;
2169 }
2170
2171 /*!
2172  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2173  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2174  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2175  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2176  *
2177  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2178  * This method method returns cells ids set s = s1 + s2 where :
2179  * 
2180  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2181  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2182  *
2183  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2184  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2185  *
2186  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2187  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2188  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2189  */
2190 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2191 {
2192   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2193     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2194   checkConnectivityFullyDefined();
2195   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2196   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2197     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2198   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2200   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2202   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2203   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2204   DataArrayInt *idsOtherInConsti=0;
2205   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2206   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2207   if(!b)
2208     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2209   std::set<int> s1;
2210   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2211     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2212   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2214   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2215   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2216   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2217   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2218   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2219   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2220   neighThisPartAuto=0;
2221   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2222   const int li[2]={0,1};
2223   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2224   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2225   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2226   s_renum1->sort();
2227   //
2228   cellIdsRk0=s0arr.retn();
2229   cellIdsRk1=s_renum1.retn();
2230 }
2231
2232 /*!
2233  * 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
2234  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2235  * 
2236  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2237  */
2238 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2239 {
2240   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2244   //
2245   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2246   revDesc=0; desc=0; descIndx=0;
2247   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2249   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2250 }
2251
2252 /*!
2253  * Finds nodes lying on the boundary of \a this mesh.
2254  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2255  *          nodes. The caller is to delete this array using decrRef() as it is no
2256  *          more needed.
2257  *  \throw If the coordinates array is not set.
2258  *  \throw If the nodal connectivity of cells is node defined.
2259  *
2260  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2261  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2262  */
2263 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2264 {
2265   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2266   return skin->computeFetchedNodeIds();
2267 }
2268
2269 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2270 {
2271   incrRef();
2272   return const_cast<MEDCouplingUMesh *>(this);
2273 }
2274
2275 /*!
2276  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2277  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2278  * 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.
2279  * 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.
2280  * 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.
2281  *
2282  * \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
2283  *             parameter is altered during the call.
2284  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2285  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2286  * \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.
2287  *
2288  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2289  */
2290 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2291                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2292 {
2293   checkFullyDefined();
2294   otherDimM1OnSameCoords.checkFullyDefined();
2295   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2296     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2297   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2298     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2299   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2300   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2301   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2302   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2303   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2304   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2308   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2309   //
2310   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2311   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2312   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2313   DataArrayInt *idsTmp=0;
2314   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2315   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2316   if(!b)
2317     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2318   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2319   DataArrayInt *tmp0=0,*tmp1=0;
2320   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2321   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2324   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2325   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2326   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2327   //
2328   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2329   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2330   nodeIdsToDuplicate=s3.retn();
2331 }
2332
2333 /*!
2334  * This method operates a modification of the connectivity and coords in \b this.
2335  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2336  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2337  * 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
2338  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2339  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2340  * 
2341  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2342  * 
2343  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2344  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2345  */
2346 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2347 {
2348   int nbOfNodes=getNumberOfNodes();
2349   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2350   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2351 }
2352
2353 /*!
2354  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2355  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2356  * This method is a generalization of shiftNodeNumbersInConn().
2357  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2358  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2359  *         this->getNumberOfNodes(), in "Old to New" mode. 
2360  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2361  *  \throw If the nodal connectivity of cells is not defined.
2362  *
2363  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2364  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2365  */
2366 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2367 {
2368   checkConnectivityFullyDefined();
2369   int *conn=getNodalConnectivity()->getPointer();
2370   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2371   int nbOfCells=getNumberOfCells();
2372   for(int i=0;i<nbOfCells;i++)
2373     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2374       {
2375         int& node=conn[iconn];
2376         if(node>=0)//avoid polyhedron separator
2377           {
2378             node=newNodeNumbersO2N[node];
2379           }
2380       }
2381   _nodal_connec->declareAsNew();
2382   updateTime();
2383 }
2384
2385 /*!
2386  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2387  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2388  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2389  * 
2390  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2391  */
2392 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2393 {
2394   checkConnectivityFullyDefined();
2395   int *conn=getNodalConnectivity()->getPointer();
2396   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2397   int nbOfCells=getNumberOfCells();
2398   for(int i=0;i<nbOfCells;i++)
2399     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2400       {
2401         int& node=conn[iconn];
2402         if(node>=0)//avoid polyhedron separator
2403           {
2404             node+=delta;
2405           }
2406       }
2407   _nodal_connec->declareAsNew();
2408   updateTime();
2409 }
2410
2411 /*!
2412  * This method operates a modification of the connectivity in \b this.
2413  * 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.
2414  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2415  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2416  * 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
2417  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2418  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2419  * 
2420  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2421  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2422  * 
2423  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2424  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2425  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2426  */
2427 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2428 {
2429   checkConnectivityFullyDefined();
2430   std::map<int,int> m;
2431   int val=offset;
2432   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2433     m[*work]=val;
2434   int *conn=getNodalConnectivity()->getPointer();
2435   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2436   int nbOfCells=getNumberOfCells();
2437   for(int i=0;i<nbOfCells;i++)
2438     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2439       {
2440         int& node=conn[iconn];
2441         if(node>=0)//avoid polyhedron separator
2442           {
2443             std::map<int,int>::iterator it=m.find(node);
2444             if(it!=m.end())
2445               node=(*it).second;
2446           }
2447       }
2448   updateTime();
2449 }
2450
2451 /*!
2452  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2453  *
2454  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2455  * After the call of this method the number of cells remains the same as before.
2456  *
2457  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2458  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2459  * be strictly in [0;this->getNumberOfCells()).
2460  *
2461  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2462  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2463  * should be contained in[0;this->getNumberOfCells()).
2464  * 
2465  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2466  */
2467 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2468 {
2469   checkConnectivityFullyDefined();
2470   int nbCells=getNumberOfCells();
2471   const int *array=old2NewBg;
2472   if(check)
2473     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2474   //
2475   const int *conn=_nodal_connec->getConstPointer();
2476   const int *connI=_nodal_connec_index->getConstPointer();
2477   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2478   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2479   const int *n2oPtr=n2o->begin();
2480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2481   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2482   newConn->copyStringInfoFrom(*_nodal_connec);
2483   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2484   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2485   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2486   //
2487   int *newC=newConn->getPointer();
2488   int *newCI=newConnI->getPointer();
2489   int loc=0;
2490   newCI[0]=loc;
2491   for(int i=0;i<nbCells;i++)
2492     {
2493       int pos=n2oPtr[i];
2494       int nbOfElts=connI[pos+1]-connI[pos];
2495       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2496       loc+=nbOfElts;
2497       newCI[i+1]=loc;
2498     }
2499   //
2500   setConnectivity(newConn,newConnI);
2501   if(check)
2502     free(const_cast<int *>(array));
2503 }
2504
2505 /*!
2506  * Finds cells whose bounding boxes intersect a given bounding box.
2507  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2508  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2509  *         zMax (if in 3D). 
2510  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2511  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2512  *         extent of the bounding box of cell to produce an addition to this bounding box.
2513  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2514  *         cells. The caller is to delete this array using decrRef() as it is no more
2515  *         needed. 
2516  *  \throw If the coordinates array is not set.
2517  *  \throw If the nodal connectivity of cells is not defined.
2518  *
2519  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2520  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2521  */
2522 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2523 {
2524   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2525   if(getMeshDimension()==-1)
2526     {
2527       elems->pushBackSilent(0);
2528       return elems.retn();
2529     }
2530   int dim=getSpaceDimension();
2531   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2532   const int* conn      = getNodalConnectivity()->getConstPointer();
2533   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2534   const double* coords = getCoords()->getConstPointer();
2535   int nbOfCells=getNumberOfCells();
2536   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2537     {
2538       for (int i=0; i<dim; i++)
2539         {
2540           elem_bb[i*2]=std::numeric_limits<double>::max();
2541           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2542         }
2543
2544       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2545         {
2546           int node= conn[inode];
2547           if(node>=0)//avoid polyhedron separator
2548             {
2549               for (int idim=0; idim<dim; idim++)
2550                 {
2551                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2552                     {
2553                       elem_bb[idim*2] = coords[node*dim+idim] ;
2554                     }
2555                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2556                     {
2557                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2558                     }
2559                 }
2560             }
2561         }
2562       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2563         elems->pushBackSilent(ielem);
2564     }
2565   return elems.retn();
2566 }
2567
2568 /*!
2569  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2570  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2571  * added in 'elems' parameter.
2572  */
2573 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2574 {
2575   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2576   if(getMeshDimension()==-1)
2577     {
2578       elems->pushBackSilent(0);
2579       return elems.retn();
2580     }
2581   int dim=getSpaceDimension();
2582   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2583   const int* conn      = getNodalConnectivity()->getConstPointer();
2584   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2585   const double* coords = getCoords()->getConstPointer();
2586   int nbOfCells=getNumberOfCells();
2587   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2588     {
2589       for (int i=0; i<dim; i++)
2590         {
2591           elem_bb[i*2]=std::numeric_limits<double>::max();
2592           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2593         }
2594
2595       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2596         {
2597           int node= conn[inode];
2598           if(node>=0)//avoid polyhedron separator
2599             {
2600               for (int idim=0; idim<dim; idim++)
2601                 {
2602                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2603                     {
2604                       elem_bb[idim*2] = coords[node*dim+idim] ;
2605                     }
2606                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2607                     {
2608                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2609                     }
2610                 }
2611             }
2612         }
2613       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2614         elems->pushBackSilent(ielem);
2615     }
2616   return elems.retn();
2617 }
2618
2619 /*!
2620  * Returns a type of a cell by its id.
2621  *  \param [in] cellId - the id of the cell of interest.
2622  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2623  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2624  */
2625 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2626 {
2627   const int *ptI=_nodal_connec_index->getConstPointer();
2628   const int *pt=_nodal_connec->getConstPointer();
2629   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2630     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2631   else
2632     {
2633       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2634       throw INTERP_KERNEL::Exception(oss.str().c_str());
2635     }
2636 }
2637
2638 /*!
2639  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2640  * This method does not throw exception if geometric type \a type is not in \a this.
2641  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2642  * The coordinates array is not considered here.
2643  *
2644  * \param [in] type the geometric type
2645  * \return cell ids in this having geometric type \a type.
2646  */
2647 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2648 {
2649   
2650   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2651   ret->alloc(0,1);
2652   checkConnectivityFullyDefined();
2653   int nbCells=getNumberOfCells();
2654   int mdim=getMeshDimension();
2655   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2656   if(mdim!=(int)cm.getDimension())
2657     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2658   const int *ptI=_nodal_connec_index->getConstPointer();
2659   const int *pt=_nodal_connec->getConstPointer();
2660   for(int i=0;i<nbCells;i++)
2661     {
2662       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2663         ret->pushBackSilent(i);
2664     }
2665   return ret.retn();
2666 }
2667
2668 /*!
2669  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2670  */
2671 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2672 {
2673   const int *ptI=_nodal_connec_index->getConstPointer();
2674   const int *pt=_nodal_connec->getConstPointer();
2675   int nbOfCells=getNumberOfCells();
2676   int ret=0;
2677   for(int i=0;i<nbOfCells;i++)
2678     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2679       ret++;
2680   return ret;
2681 }
2682
2683 /*!
2684  * Returns the nodal connectivity of a given cell.
2685  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2686  * all returned node ids can be used in getCoordinatesOfNode().
2687  *  \param [in] cellId - an id of the cell of interest.
2688  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2689  *         cleared before the appending.
2690  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2691  */
2692 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2693 {
2694   const int *ptI=_nodal_connec_index->getConstPointer();
2695   const int *pt=_nodal_connec->getConstPointer();
2696   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2697     if(*w>=0)
2698       conn.push_back(*w);
2699 }
2700
2701 std::string MEDCouplingUMesh::simpleRepr() const
2702 {
2703   static const char msg0[]="No coordinates specified !";
2704   std::ostringstream ret;
2705   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2706   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2707   int tmpp1,tmpp2;
2708   double tt=getTime(tmpp1,tmpp2);
2709   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2710   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2711   if(_mesh_dim>=-1)
2712     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2713   else
2714     { ret << " Mesh dimension has not been set or is invalid !"; }
2715   if(_coords!=0)
2716     {
2717       const int spaceDim=getSpaceDimension();
2718       ret << spaceDim << "\nInfo attached on space dimension : ";
2719       for(int i=0;i<spaceDim;i++)
2720         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2721       ret << "\n";
2722     }
2723   else
2724     ret << msg0 << "\n";
2725   ret << "Number of nodes : ";
2726   if(_coords!=0)
2727     ret << getNumberOfNodes() << "\n";
2728   else
2729     ret << msg0 << "\n";
2730   ret << "Number of cells : ";
2731   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2732     ret << getNumberOfCells() << "\n";
2733   else
2734     ret << "No connectivity specified !" << "\n";
2735   ret << "Cell types present : ";
2736   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2737     {
2738       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2739       ret << cm.getRepr() << " ";
2740     }
2741   ret << "\n";
2742   return ret.str();
2743 }
2744
2745 std::string MEDCouplingUMesh::advancedRepr() const
2746 {
2747   std::ostringstream ret;
2748   ret << simpleRepr();
2749   ret << "\nCoordinates array : \n___________________\n\n";
2750   if(_coords)
2751     _coords->reprWithoutNameStream(ret);
2752   else
2753     ret << "No array set !\n";
2754   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2755   reprConnectivityOfThisLL(ret);
2756   return ret.str();
2757 }
2758
2759 /*!
2760  * This method returns a C++ code that is a dump of \a this.
2761  * This method will throw if this is not fully defined.
2762  */
2763 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2764 {
2765   static const char coordsName[]="coords";
2766   static const char connName[]="conn";
2767   static const char connIName[]="connI";
2768   checkFullyDefined();
2769   std::ostringstream ret; ret << "// coordinates" << std::endl;
2770   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2771   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2772   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2773   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2774   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2775   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2776   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2777   return ret.str();
2778 }
2779
2780 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2781 {
2782   std::ostringstream ret;
2783   reprConnectivityOfThisLL(ret);
2784   return ret.str();
2785 }
2786
2787 /*!
2788  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2789  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2790  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2791  * some algos).
2792  * 
2793  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2794  * 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
2795  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2796  */
2797 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2798 {
2799   int mdim=getMeshDimension();
2800   if(mdim<0)
2801     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2802   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2803   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2804   bool needToCpyCT=true;
2805   if(!_nodal_connec)
2806     {
2807       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2808       needToCpyCT=false;
2809     }
2810   else
2811     {
2812       tmp1=_nodal_connec;
2813       tmp1->incrRef();
2814     }
2815   if(!_nodal_connec_index)
2816     {
2817       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2818       needToCpyCT=false;
2819     }
2820   else
2821     {
2822       tmp2=_nodal_connec_index;
2823       tmp2->incrRef();
2824     }
2825   ret->setConnectivity(tmp1,tmp2,false);
2826   if(needToCpyCT)
2827     ret->_types=_types;
2828   if(!_coords)
2829     {
2830       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2831       ret->setCoords(coords);
2832     }
2833   else
2834     ret->setCoords(_coords);
2835   return ret.retn();
2836 }
2837
2838 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2839 {
2840   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2841     {
2842       int nbOfCells=getNumberOfCells();
2843       const int *c=_nodal_connec->getConstPointer();
2844       const int *ci=_nodal_connec_index->getConstPointer();
2845       for(int i=0;i<nbOfCells;i++)
2846         {
2847           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2848           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2849           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2850           stream << "\n";
2851         }
2852     }
2853   else
2854     stream << "Connectivity not defined !\n";
2855 }
2856
2857 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2858 {
2859   const int *ptI=_nodal_connec_index->getConstPointer();
2860   const int *pt=_nodal_connec->getConstPointer();
2861   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2862     return ptI[cellId+1]-ptI[cellId]-1;
2863   else
2864     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2865 }
2866
2867 /*!
2868  * Returns types of cells of the specified part of \a this mesh.
2869  * This method avoids computing sub-mesh explicitely to get its types.
2870  *  \param [in] begin - an array of cell ids of interest.
2871  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2872  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2873  *         describing the cell types. 
2874  *  \throw If the coordinates array is not set.
2875  *  \throw If the nodal connectivity of cells is not defined.
2876  *  \sa getAllTypes()
2877  */
2878 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2879 {
2880   checkFullyDefined();
2881   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2882   const int *conn=_nodal_connec->getConstPointer();
2883   const int *connIndex=_nodal_connec_index->getConstPointer();
2884   for(const int *w=begin;w!=end;w++)
2885     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2886   return ret;
2887 }
2888
2889 /*!
2890  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2891  * a set of types of cells constituting \a this mesh. 
2892  * This method is for advanced users having prepared their connectivity before. For
2893  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2894  *  \param [in] conn - the nodal connectivity array. 
2895  *  \param [in] connIndex - the nodal connectivity index array.
2896  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2897  *         mesh is updated.
2898  */
2899 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2900 {
2901   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2902   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2903   if(isComputingTypes)
2904     computeTypes();
2905   declareAsNew();
2906 }
2907
2908 /*!
2909  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2910  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2911  */
2912 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2913                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2914                                                                                 _types(other._types)
2915 {
2916   if(other._nodal_connec)
2917     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2918   if(other._nodal_connec_index)
2919     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2920 }
2921
2922 MEDCouplingUMesh::~MEDCouplingUMesh()
2923 {
2924   if(_nodal_connec)
2925     _nodal_connec->decrRef();
2926   if(_nodal_connec_index)
2927     _nodal_connec_index->decrRef();
2928 }
2929
2930 /*!
2931  * Recomputes a set of cell types of \a this mesh. For more info see
2932  * \ref MEDCouplingUMeshNodalConnectivity.
2933  */
2934 void MEDCouplingUMesh::computeTypes()
2935 {
2936   if(_nodal_connec && _nodal_connec_index)
2937     {
2938       _types.clear();
2939       const int *conn=_nodal_connec->getConstPointer();
2940       const int *connIndex=_nodal_connec_index->getConstPointer();
2941       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2942       if (nbOfElem > 0)
2943         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2944           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2945     }
2946 }
2947
2948 /*!
2949  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2950  */
2951 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2952 {
2953   if(!_nodal_connec_index || !_nodal_connec || !_coords)
2954     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2955 }
2956
2957 /*!
2958  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2959  */
2960 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2961 {
2962   if(!_nodal_connec_index || !_nodal_connec)
2963     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2964 }
2965
2966 /*!
2967  * Returns a number of cells constituting \a this mesh. 
2968  *  \return int - the number of cells in \a this mesh.
2969  *  \throw If the nodal connectivity of cells is not defined.
2970  */
2971 int MEDCouplingUMesh::getNumberOfCells() const
2972
2973   if(_nodal_connec_index)
2974     return _nodal_connec_index->getNumberOfTuples()-1;
2975   else
2976     if(_mesh_dim==-1)
2977       return 1;
2978     else
2979       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2980 }
2981
2982 /*!
2983  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
2984  * mesh. For more info see \ref MEDCouplingMeshesPage.
2985  *  \return int - the dimension of \a this mesh.
2986  *  \throw If the mesh dimension is not defined using setMeshDimension().
2987  */
2988 int MEDCouplingUMesh::getMeshDimension() const
2989 {
2990   if(_mesh_dim<-1)
2991     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2992   return _mesh_dim;
2993 }
2994
2995 /*!
2996  * Returns a length of the nodal connectivity array.
2997  * This method is for test reason. Normally the integer returned is not useable by
2998  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
2999  *  \return int - the length of the nodal connectivity array.
3000  */
3001 int MEDCouplingUMesh::getMeshLength() const
3002 {
3003   return _nodal_connec->getNbOfElems();
3004 }
3005
3006 /*!
3007  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3008  */
3009 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3010 {
3011   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3012   tinyInfo.push_back(getMeshDimension());
3013   tinyInfo.push_back(getNumberOfCells());
3014   if(_nodal_connec)
3015     tinyInfo.push_back(getMeshLength());
3016   else
3017     tinyInfo.push_back(-1);
3018 }
3019
3020 /*!
3021  * First step of unserialization process.
3022  */
3023 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3024 {
3025   return tinyInfo[6]<=0;
3026 }
3027
3028 /*!
3029  * Second step of serialization process.
3030  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3031  */
3032 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3033 {
3034   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3035   if(tinyInfo[5]!=-1)
3036     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3037 }
3038
3039 /*!
3040  * Third and final step of serialization process.
3041  */
3042 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3043 {
3044   MEDCouplingPointSet::serialize(a1,a2);
3045   if(getMeshDimension()>-1)
3046     {
3047       a1=DataArrayInt::New();
3048       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3049       int *ptA1=a1->getPointer();
3050       const int *conn=getNodalConnectivity()->getConstPointer();
3051       const int *index=getNodalConnectivityIndex()->getConstPointer();
3052       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3053       std::copy(conn,conn+getMeshLength(),ptA1);
3054     }
3055   else
3056     a1=0;
3057 }
3058
3059 /*!
3060  * Second and final unserialization process.
3061  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3062  */
3063 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3064 {
3065   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3066   setMeshDimension(tinyInfo[5]);
3067   if(tinyInfo[7]!=-1)
3068     {
3069       // Connectivity
3070       const int *recvBuffer=a1->getConstPointer();
3071       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3072       myConnecIndex->alloc(tinyInfo[6]+1,1);
3073       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3074       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3075       myConnec->alloc(tinyInfo[7],1);
3076       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3077       setConnectivity(myConnec, myConnecIndex);
3078     }
3079 }
3080
3081 /*!
3082  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3083  * CellIds are given using range specified by a start an end and step.
3084  */
3085 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3086 {
3087   checkFullyDefined();
3088   int ncell=getNumberOfCells();
3089   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3090   ret->_mesh_dim=_mesh_dim;
3091   ret->setCoords(_coords);
3092   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3093   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3094   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3095   int work=start;
3096   const int *conn=_nodal_connec->getConstPointer();
3097   const int *connIndex=_nodal_connec_index->getConstPointer();
3098   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3099     {
3100       if(work>=0 && work<ncell)
3101         {
3102           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3103         }
3104       else
3105         {
3106           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3107           throw INTERP_KERNEL::Exception(oss.str().c_str());
3108         }
3109     }
3110   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3111   int *newConnPtr=newConn->getPointer();
3112   std::set<INTERP_KERNEL::NormalizedCellType> types;
3113   work=start;
3114   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3115     {
3116       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3117       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3118     }
3119   ret->setConnectivity(newConn,newConnI,false);
3120   ret->_types=types;
3121   ret->copyTinyInfoFrom(this);
3122   return ret.retn();
3123 }
3124
3125 /*!
3126  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3127  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3128  * The return newly allocated mesh will share the same coordinates as \a this.
3129  */
3130 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3131 {
3132   checkConnectivityFullyDefined();
3133   int ncell=getNumberOfCells();
3134   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3135   ret->_mesh_dim=_mesh_dim;
3136   ret->setCoords(_coords);
3137   std::size_t nbOfElemsRet=std::distance(begin,end);
3138   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3139   connIndexRet[0]=0;
3140   const int *conn=_nodal_connec->getConstPointer();
3141   const int *connIndex=_nodal_connec_index->getConstPointer();
3142   int newNbring=0;
3143   for(const int *work=begin;work!=end;work++,newNbring++)
3144     {
3145       if(*work>=0 && *work<ncell)
3146         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3147       else
3148         {
3149           free(connIndexRet);
3150           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3151           throw INTERP_KERNEL::Exception(oss.str().c_str());
3152         }
3153     }
3154   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3155   int *connRetWork=connRet;
3156   std::set<INTERP_KERNEL::NormalizedCellType> types;
3157   for(const int *work=begin;work!=end;work++)
3158     {
3159       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3160       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3161     }
3162   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3163   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3164   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3165   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3166   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3167   ret->_types=types;
3168   ret->copyTinyInfoFrom(this);
3169   return ret.retn();
3170 }
3171
3172 /*!
3173  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3174  * mesh.<br>
3175  * For 1D cells, the returned field contains lengths.<br>
3176  * For 2D cells, the returned field contains areas.<br>
3177  * For 3D cells, the returned field contains volumes.
3178  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3179  *         orientation, i.e. the volume is always positive.
3180  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3181  *         and one time . The caller is to delete this field using decrRef() as it is no
3182  *         more needed.
3183  */
3184 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3185 {
3186   std::string name="MeasureOfMesh_";
3187   name+=getName();
3188   int nbelem=getNumberOfCells();
3189   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3190   field->setName(name.c_str());
3191   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3192   array->alloc(nbelem,1);
3193   double *area_vol=array->getPointer();
3194   field->setArray(array) ; array=0;
3195   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3196   field->synchronizeTimeWithMesh();
3197   if(getMeshDimension()!=-1)
3198     {
3199       int ipt;
3200       INTERP_KERNEL::NormalizedCellType type;
3201       int dim_space=getSpaceDimension();
3202       const double *coords=getCoords()->getConstPointer();
3203       const int *connec=getNodalConnectivity()->getConstPointer();
3204       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3205       for(int iel=0;iel<nbelem;iel++)
3206         {
3207           ipt=connec_index[iel];
3208           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3209           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);
3210         }
3211       if(isAbs)
3212         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3213     }
3214   else
3215     {
3216       area_vol[0]=std::numeric_limits<double>::max();
3217     }
3218   return field.retn();
3219 }
3220
3221 /*!
3222  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3223  * mesh.<br>
3224  * For 1D cells, the returned array contains lengths.<br>
3225  * For 2D cells, the returned array contains areas.<br>
3226  * For 3D cells, the returned array contains volumes.
3227  * This method avoids building explicitly a part of \a this mesh to perform the work.
3228  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3229  *         orientation, i.e. the volume is always positive.
3230  *  \param [in] begin - an array of cell ids of interest.
3231  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3232  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3233  *          delete this array using decrRef() as it is no more needed.
3234  * 
3235  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3236  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3237  *  \sa getMeasureField()
3238  */
3239 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3240 {
3241   std::string name="PartMeasureOfMesh_";
3242   name+=getName();
3243   int nbelem=(int)std::distance(begin,end);
3244   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3245   array->setName(name.c_str());
3246   array->alloc(nbelem,1);
3247   double *area_vol=array->getPointer();
3248   if(getMeshDimension()!=-1)
3249     {
3250       int ipt;
3251       INTERP_KERNEL::NormalizedCellType type;
3252       int dim_space=getSpaceDimension();
3253       const double *coords=getCoords()->getConstPointer();
3254       const int *connec=getNodalConnectivity()->getConstPointer();
3255       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3256       for(const int *iel=begin;iel!=end;iel++)
3257         {
3258           ipt=connec_index[*iel];
3259           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3260           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3261         }
3262       if(isAbs)
3263         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3264     }
3265   else
3266     {
3267       area_vol[0]=std::numeric_limits<double>::max();
3268     }
3269   return array.retn();
3270 }
3271
3272 /*!
3273  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3274  * \a this one. The returned field contains the dual cell volume for each corresponding
3275  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3276  *  the dual mesh in P1 sens of \a this.<br>
3277  * For 1D cells, the returned field contains lengths.<br>
3278  * For 2D cells, the returned field contains areas.<br>
3279  * For 3D cells, the returned field contains volumes.
3280  * This method is useful to check "P1*" conservative interpolators.
3281  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3282  *         orientation, i.e. the volume is always positive.
3283  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3284  *          nodes and one time. The caller is to delete this array using decrRef() as
3285  *          it is no more needed.
3286  */
3287 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3288 {
3289   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3290   std::string name="MeasureOnNodeOfMesh_";
3291   name+=getName();
3292   int nbNodes=getNumberOfNodes();
3293   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3294   double cst=1./((double)getMeshDimension()+1.);
3295   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3296   array->alloc(nbNodes,1);
3297   double *valsToFill=array->getPointer();
3298   std::fill(valsToFill,valsToFill+nbNodes,0.);
3299   const double *values=tmp->getArray()->getConstPointer();
3300   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3301   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3302   getReverseNodalConnectivity(da,daInd);
3303   const int *daPtr=da->getConstPointer();
3304   const int *daIPtr=daInd->getConstPointer();
3305   for(int i=0;i<nbNodes;i++)
3306     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3307       valsToFill[i]+=cst*values[*cell];
3308   ret->setMesh(this);
3309   ret->setArray(array);
3310   return ret.retn();
3311 }
3312
3313 /*!
3314  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3315  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3316  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3317  * and are normalized.
3318  * <br> \a this can be either 
3319  * - a  2D mesh in 2D or 3D space or 
3320  * - an 1D mesh in 2D space.
3321  * 
3322  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3323  *          cells and one time. The caller is to delete this field using decrRef() as
3324  *          it is no more needed.
3325  *  \throw If the nodal connectivity of cells is not defined.
3326  *  \throw If the coordinates array is not set.
3327  *  \throw If the mesh dimension is not set.
3328  *  \throw If the mesh and space dimension is not as specified above.
3329  */
3330 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3331 {
3332   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3333     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3334   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3335   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3336   int nbOfCells=getNumberOfCells();
3337   int nbComp=getMeshDimension()+1;
3338   array->alloc(nbOfCells,nbComp);
3339   double *vals=array->getPointer();
3340   const int *connI=_nodal_connec_index->getConstPointer();
3341   const int *conn=_nodal_connec->getConstPointer();
3342   const double *coords=_coords->getConstPointer();
3343   if(getMeshDimension()==2)
3344     {
3345       if(getSpaceDimension()==3)
3346         {
3347           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3348           const double *locPtr=loc->getConstPointer();
3349           for(int i=0;i<nbOfCells;i++,vals+=3)
3350             {
3351               int offset=connI[i];
3352               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3353               double n=INTERP_KERNEL::norm<3>(vals);
3354               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3355             }
3356         }
3357       else
3358         {
3359           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3360           const double *isAbsPtr=isAbs->getArray()->begin();
3361           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3362             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3363         }
3364     }
3365   else//meshdimension==1
3366     {
3367       double tmp[2];
3368       for(int i=0;i<nbOfCells;i++)
3369         {
3370           int offset=connI[i];
3371           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3372           double n=INTERP_KERNEL::norm<2>(tmp);
3373           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3374           *vals++=-tmp[1];
3375           *vals++=tmp[0];
3376         }
3377     }
3378   ret->setArray(array);
3379   ret->setMesh(this);
3380   ret->synchronizeTimeWithSupport();
3381   return ret.retn();
3382 }
3383
3384 /*!
3385  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3386  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3387  * and are normalized.
3388  * <br> \a this can be either 
3389  * - a  2D mesh in 2D or 3D space or 
3390  * - an 1D mesh in 2D space.
3391  * 
3392  * This method avoids building explicitly a part of \a this mesh to perform the work.
3393  *  \param [in] begin - an array of cell ids of interest.
3394  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3395  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3396  *          cells and one time. The caller is to delete this field using decrRef() as
3397  *          it is no more needed.
3398  *  \throw If the nodal connectivity of cells is not defined.
3399  *  \throw If the coordinates array is not set.
3400  *  \throw If the mesh dimension is not set.
3401  *  \throw If the mesh and space dimension is not as specified above.
3402  *  \sa buildOrthogonalField()
3403  *
3404  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3405  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3406  */
3407 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3408 {
3409   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3410     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3411   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3412   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3413   std::size_t nbelems=std::distance(begin,end);
3414   int nbComp=getMeshDimension()+1;
3415   array->alloc((int)nbelems,nbComp);
3416   double *vals=array->getPointer();
3417   const int *connI=_nodal_connec_index->getConstPointer();
3418   const int *conn=_nodal_connec->getConstPointer();
3419   const double *coords=_coords->getConstPointer();
3420   if(getMeshDimension()==2)
3421     {
3422       if(getSpaceDimension()==3)
3423         {
3424           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3425           const double *locPtr=loc->getConstPointer();
3426           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3427             {
3428               int offset=connI[*i];
3429               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3430               double n=INTERP_KERNEL::norm<3>(vals);
3431               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3432             }
3433         }
3434       else
3435         {
3436           for(std::size_t i=0;i<nbelems;i++)
3437             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3438         }
3439     }
3440   else//meshdimension==1
3441     {
3442       double tmp[2];
3443       for(const int *i=begin;i!=end;i++)
3444         {
3445           int offset=connI[*i];
3446           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3447           double n=INTERP_KERNEL::norm<2>(tmp);
3448           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3449           *vals++=-tmp[1];
3450           *vals++=tmp[0];
3451         }
3452     }
3453   ret->setArray(array);
3454   ret->setMesh(this);
3455   ret->synchronizeTimeWithSupport();
3456   return ret.retn();
3457 }
3458
3459 /*!
3460  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3461  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3462  * and are \b not normalized.
3463  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3464  *          cells and one time. The caller is to delete this field using decrRef() as
3465  *          it is no more needed.
3466  *  \throw If the nodal connectivity of cells is not defined.
3467  *  \throw If the coordinates array is not set.
3468  *  \throw If \a this->getMeshDimension() != 1.
3469  *  \throw If \a this mesh includes cells of type other than SEG2.
3470  */
3471 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3472 {
3473    if(getMeshDimension()!=1)
3474     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3475    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3476      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3477    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3478    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3479    int nbOfCells=getNumberOfCells();
3480    int spaceDim=getSpaceDimension();
3481    array->alloc(nbOfCells,spaceDim);
3482    double *pt=array->getPointer();
3483    const double *coo=getCoords()->getConstPointer();
3484    std::vector<int> conn;
3485    conn.reserve(2);
3486    for(int i=0;i<nbOfCells;i++)
3487      {
3488        conn.resize(0);
3489        getNodeIdsOfCell(i,conn);
3490        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3491      }
3492    ret->setArray(array);
3493    ret->setMesh(this);
3494    ret->synchronizeTimeWithSupport();
3495    return ret.retn();   
3496 }
3497
3498 /*!
3499  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3500  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3501  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3502  * from. If a result face is shared by two 3D cells, then the face in included twice in
3503  * the result mesh.
3504  *  \param [in] origin - 3 components of a point defining location of the plane.
3505  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3506  *         must be greater than 1e-6.
3507  *  \param [in] eps - half-thickness of the plane.
3508  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3509  *         producing correspondent 2D cells. The caller is to delete this array
3510  *         using decrRef() as it is no more needed.
3511  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3512  *         not share the node coordinates array with \a this mesh. The caller is to
3513  *         delete this mesh using decrRef() as it is no more needed.  
3514  *  \throw If the coordinates array is not set.
3515  *  \throw If the nodal connectivity of cells is not defined.
3516  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3517  *  \throw If magnitude of \a vec is less than 1e-6.
3518  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3519  *  \throw If \a this includes quadratic cells.
3520  */
3521 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3522 {
3523   checkFullyDefined();
3524   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3525     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3526   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3527   if(candidates->empty())
3528     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3529   std::vector<int> nodes;
3530   DataArrayInt *cellIds1D=0;
3531   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3532   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3533   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3534   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3535   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3536   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3537   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3538   revDesc2=0; revDescIndx2=0;
3539   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3540   revDesc1=0; revDescIndx1=0;
3541   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3542   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3543   //
3544   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3545   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3546     cut3DCurve[*it]=-1;
3547   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3548   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3549   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3550                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3551                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3552   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3553   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3554   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3555   if(cellIds2->empty())
3556     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3557   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3558   ret->setCoords(mDesc1->getCoords());
3559   ret->setConnectivity(conn,connI,true);
3560   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3561   return ret.retn();
3562 }
3563
3564 /*!
3565  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3566 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
3567 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3568 the result mesh.
3569  *  \param [in] origin - 3 components of a point defining location of the plane.
3570  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3571  *         must be greater than 1e-6.
3572  *  \param [in] eps - half-thickness of the plane.
3573  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3574  *         producing correspondent segments. The caller is to delete this array
3575  *         using decrRef() as it is no more needed.
3576  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3577  *         mesh in 3D space. This mesh does not share the node coordinates array with
3578  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3579  *         no more needed. 
3580  *  \throw If the coordinates array is not set.
3581  *  \throw If the nodal connectivity of cells is not defined.
3582  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3583  *  \throw If magnitude of \a vec is less than 1e-6.
3584  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3585  *  \throw If \a this includes quadratic cells.
3586  */
3587 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3588 {
3589   checkFullyDefined();
3590   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3591     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3592   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3593   if(candidates->empty())
3594     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3595   std::vector<int> nodes;
3596   DataArrayInt *cellIds1D=0;
3597   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3598   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3599   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3600   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3601   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3602   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3603   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3604   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3605   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3606   //
3607   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3608   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3609     cut3DCurve[*it]=-1;
3610   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3611   int ncellsSub=subMesh->getNumberOfCells();
3612   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3613   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3614                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3615                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3616   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3617   conn->alloc(0,1);
3618   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3619   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3620   for(int i=0;i<ncellsSub;i++)
3621     {
3622       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3623         {
3624           if(cut3DSurf[i].first!=-2)
3625             {
3626               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3627               connI->pushBackSilent(conn->getNumberOfTuples());
3628               cellIds2->pushBackSilent(i);
3629             }
3630           else
3631             {
3632               int cellId3DSurf=cut3DSurf[i].second;
3633               int offset=nodalI[cellId3DSurf]+1;
3634               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3635               for(int j=0;j<nbOfEdges;j++)
3636                 {
3637                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3638                   connI->pushBackSilent(conn->getNumberOfTuples());
3639                   cellIds2->pushBackSilent(cellId3DSurf);
3640                 }
3641             }
3642         }
3643     }
3644   if(cellIds2->empty())
3645     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3646   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3647   ret->setCoords(mDesc1->getCoords());
3648   ret->setConnectivity(conn,connI,true);
3649   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3650   return ret.retn();
3651 }
3652
3653 /*!
3654  * Finds cells whose bounding boxes intersect a given plane.
3655  *  \param [in] origin - 3 components of a point defining location of the plane.
3656  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3657  *         must be greater than 1e-6.
3658  *  \param [in] eps - half-thickness of the plane.
3659  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3660  *         cells. The caller is to delete this array using decrRef() as it is no more
3661  *         needed.
3662  *  \throw If the coordinates array is not set.
3663  *  \throw If the nodal connectivity of cells is not defined.
3664  *  \throw If \a this->getSpaceDimension() != 3.
3665  *  \throw If magnitude of \a vec is less than 1e-6.
3666  *  \sa buildSlice3D()
3667  */
3668 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3669 {
3670   checkFullyDefined();
3671   if(getSpaceDimension()!=3)
3672     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3673   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3674   if(normm<1e-6)
3675     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3676   double vec2[3];
3677   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3678   double angle=acos(vec[2]/normm);
3679   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3680   double bbox[6];
3681   if(angle>eps)
3682     {
3683       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3684       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3685       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3686       mw->setCoords(coo);
3687       mw->getBoundingBox(bbox);
3688       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3689       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3690     }
3691   else
3692     {
3693       getBoundingBox(bbox);
3694       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3695       cellIds=getCellsInBoundingBox(bbox,eps);
3696     }
3697   return cellIds.retn();
3698 }
3699
3700 /*!
3701  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3702  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3703  * No consideration of coordinate is done by this method.
3704  * 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)
3705  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3706  */
3707 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3708 {
3709   if(getMeshDimension()!=1)
3710     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3711   int nbCells=getNumberOfCells();
3712   if(nbCells<1)
3713     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3714   const int *connI=_nodal_connec_index->getConstPointer();
3715   const int *conn=_nodal_connec->getConstPointer();
3716   int ref=conn[connI[0]+2];
3717   for(int i=1;i<nbCells;i++)
3718     {
3719       if(conn[connI[i]+1]!=ref)
3720         return false;
3721       ref=conn[connI[i]+2];
3722     }
3723   return true;
3724 }
3725
3726 /*!
3727  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3728  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3729  * \param pt reference point of the line
3730  * \param v normalized director vector of the line
3731  * \param eps max precision before throwing an exception
3732  * \param res output of size this->getNumberOfCells
3733  */
3734 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3735 {
3736   if(getMeshDimension()!=1)
3737     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3738    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3739      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3740    if(getSpaceDimension()!=3)
3741      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3742    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3743    const double *fPtr=f->getArray()->getConstPointer();
3744    double tmp[3];
3745    for(int i=0;i<getNumberOfCells();i++)
3746      {
3747        const double *tmp1=fPtr+3*i;
3748        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3749        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3750        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3751        double n1=INTERP_KERNEL::norm<3>(tmp);
3752        n1/=INTERP_KERNEL::norm<3>(tmp1);
3753        if(n1>eps)
3754          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3755      }
3756    const double *coo=getCoords()->getConstPointer();
3757    for(int i=0;i<getNumberOfNodes();i++)
3758      {
3759        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3760        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3761        res[i]=std::accumulate(tmp,tmp+3,0.);
3762      }
3763 }
3764
3765 /*!
3766  * 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. 
3767  * \a this is expected to be a mesh so that its space dimension is equal to its
3768  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3769  * 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).
3770  
3771  * 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
3772  * 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).
3773  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3774  *
3775  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3776  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3777  *
3778  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3779  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3780  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3781  * \return the positive value of the distance.
3782  * \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
3783  * dimension - 1.
3784  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3785  */
3786 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3787 {
3788   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3789   if(meshDim!=spaceDim-1)
3790     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3791   if(meshDim!=2 && meshDim!=1)
3792     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3793   checkFullyDefined();
3794   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3795     { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
3796   DataArrayInt *ret1=0;
3797   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3798   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3799   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3800   cellId=*ret1Safe->begin();
3801   return *ret0->begin();
3802 }
3803
3804 /*!
3805  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3806  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3807  * 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
3808  * 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).
3809  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3810  * 
3811  * \a this is expected to be a mesh so that its space dimension is equal to its
3812  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3813  * 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).
3814  *
3815  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3816  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3817  *
3818  * \param [in] pts the list of points in which each tuple represents a point
3819  * \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.
3820  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3821  * \throw if number of components of \a pts is not equal to the space dimension.
3822  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3823  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3824  */
3825 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3826 {
3827   if(!pts)
3828     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3829   pts->checkAllocated();
3830   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3831   if(meshDim!=spaceDim-1)
3832     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3833   if(meshDim!=2 && meshDim!=1)
3834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3835   if(pts->getNumberOfComponents()!=spaceDim)
3836     {
3837       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3838       throw INTERP_KERNEL::Exception(oss.str().c_str());
3839     }
3840   checkFullyDefined();
3841   int nbCells=getNumberOfCells();
3842   if(nbCells==0)
3843     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3844   int nbOfPts=pts->getNumberOfTuples();
3845   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3846   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3847   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3848   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3849   std::vector<double> bbox;
3850   getBoundingBoxForBBTree(bbox);
3851   switch(spaceDim)
3852     {
3853     case 3:
3854       {
3855         BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3856         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3857           {
3858             double x=std::numeric_limits<double>::max();
3859             std::vector<int> elems;
3860             myTree.getMinDistanceOfMax(ptsPtr,x);
3861             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3862             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3863           }
3864         break;
3865       }
3866     case 2:
3867       {
3868         BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3869         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3870           {
3871             double x=std::numeric_limits<double>::max();
3872             std::vector<int> elems;
3873             myTree.getMinDistanceOfMax(ptsPtr,x);
3874             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3875             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3876           }
3877         break;
3878       }
3879     default:
3880       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3881     }
3882   cellIds=ret1.retn();
3883   return ret0.retn();
3884 }
3885
3886 /*!
3887  * \param [in] pt the start pointer (included) of the coordinates of the point
3888  * \param [in] cellIdsBg the start pointer (included) of cellIds
3889  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3890  * \param [in] nc nodal connectivity
3891  * \param [in] ncI nodal connectivity index
3892  * \param [in,out] ret0 the min distance between \a this and the external input point
3893  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3894  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3895  */
3896 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
3897 {
3898   cellId=-1;
3899   ret0=std::numeric_limits<double>::max();
3900   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3901     {
3902       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3903         {
3904         case INTERP_KERNEL::NORM_TRI3:
3905           {
3906             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3907             if(tmp<ret0)
3908               { ret0=tmp; cellId=*zeCell; }
3909             break;
3910           }
3911         case INTERP_KERNEL::NORM_QUAD4:
3912         case INTERP_KERNEL::NORM_POLYGON:
3913           {
3914             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3915             if(tmp<ret0)
3916               { ret0=tmp; cellId=*zeCell; }
3917             break;
3918           }
3919         default:
3920           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3921         }
3922     }
3923 }
3924
3925 /*!
3926  * \param [in] pt the start pointer (included) of the coordinates of the point
3927  * \param [in] cellIdsBg the start pointer (included) of cellIds
3928  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3929  * \param [in] nc nodal connectivity
3930  * \param [in] ncI nodal connectivity index
3931  * \param [in,out] ret0 the min distance between \a this and the external input point
3932  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3933  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3934  */
3935 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
3936 {
3937   cellId=-1;
3938   ret0=std::numeric_limits<double>::max();
3939   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3940     {
3941        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3942         {
3943         case INTERP_KERNEL::NORM_SEG2:
3944           {
3945             std::size_t uselessEntry=0;
3946             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3947             tmp=sqrt(tmp);
3948             if(tmp<ret0)
3949               { ret0=tmp; cellId=*zeCell; }
3950             break;
3951           }
3952         default:
3953           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3954         }
3955     }
3956 }
3957
3958 /*!
3959  * Finds cells in contact with a ball (i.e. a point with precision). 
3960  * \warning This method is suitable if the caller intends to evaluate only one
3961  *          point, for more points getCellsContainingPoints() is recommended as it is
3962  *          faster. 
3963  *  \param [in] pos - array of coordinates of the ball central point.
3964  *  \param [in] eps - ball radius.
3965  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
3966  *         if there are no such cells.
3967  *  \throw If the coordinates array is not set.
3968  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
3969  */
3970 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3971 {
3972   std::vector<int> elts;
3973   getCellsContainingPoint(pos,eps,elts);
3974   if(elts.empty())
3975     return -1;
3976   return elts.front();
3977 }
3978
3979 /*!
3980  * Finds cells in contact with a ball (i.e. a point with precision).
3981  * \warning This method is suitable if the caller intends to evaluate only one
3982  *          point, for more points getCellsContainingPoints() is recommended as it is
3983  *          faster. 
3984  *  \param [in] pos - array of coordinates of the ball central point.
3985  *  \param [in] eps - ball radius.
3986  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
3987  *         before inserting ids.
3988  *  \throw If the coordinates array is not set.
3989  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
3990  *
3991  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
3992  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
3993  */
3994 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3995 {
3996   std::vector<int> eltsIndex;
3997   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
3998 }
3999
4000 /// @cond INTERNAL
4001
4002 namespace ParaMEDMEM
4003 {
4004   template<const int SPACEDIMM>
4005   class DummyClsMCUG
4006   {
4007   public:
4008     static const int MY_SPACEDIM=SPACEDIMM;
4009     static const int MY_MESHDIM=8;
4010     typedef int MyConnType;
4011     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4012     // begin
4013     // useless, but for windows compilation ...
4014     const double* getCoordinatesPtr() const { return 0; }
4015     const int* getConnectivityPtr() const { return 0; }
4016     const int* getConnectivityIndexPtr() const { return 0; }
4017     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4018     // end
4019   };
4020
4021   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4022   {
4023     INTERP_KERNEL::Edge *ret=0;
4024     switch(typ)
4025       {
4026       case INTERP_KERNEL::NORM_SEG2:
4027         {
4028           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4029           break;
4030         }
4031       case INTERP_KERNEL::NORM_SEG3:
4032         {
4033           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4034           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4035           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4036           bool colinearity=inters.areColinears();
4037           delete e1; delete e2;
4038           if(colinearity)
4039             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4040           else
4041             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4042           mapp2[bg[2]].second=false;
4043           break;
4044         }
4045       default:
4046         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4047       }
4048     return ret;
4049   }
4050
4051   /*!
4052    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
4053    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4054    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4055    */
4056   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4057   {
4058     mapp.clear();
4059     std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;//bool is for a flag specifying if node is boundary (true) or only a middle for SEG3.
4060     const double *coo=mDesc->getCoords()->getConstPointer();
4061     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4062     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4063     std::set<int> s;
4064     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4065       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4066     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4067       {
4068         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4069         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4070       }
4071     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4072     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4073       {
4074         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4075         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4076       }
4077     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4078       {
4079         if((*it2).second.second)
4080           mapp[(*it2).second.first]=(*it2).first;
4081         ((*it2).second.first)->decrRef();
4082       }
4083     return ret;
4084   }
4085
4086   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4087   {
4088     if(nodeId>=offset2)
4089       {
4090         int locId=nodeId-offset2;
4091         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4092       }
4093     if(nodeId>=offset1)
4094       {
4095         int locId=nodeId-offset1;
4096         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4097       }
4098     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4099   }
4100
4101   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4102                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4103                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4104   {
4105     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4106       {
4107         int eltId1=abs(*desc1)-1;
4108         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4109           {
4110             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4111             if(it==mappRev.end())
4112               {
4113                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4114                 mapp[node]=*it1;
4115                 mappRev[*it1]=node;
4116               }
4117           }
4118       }
4119   }
4120 }
4121
4122 /// @endcond
4123
4124 template<int SPACEDIM>
4125 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4126                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4127 {
4128   std::vector<double> bbox;
4129   eltsIndex.resize(nbOfPoints+1);
4130   eltsIndex[0]=0;
4131   elts.clear();
4132   getBoundingBoxForBBTree(bbox);
4133   int nbOfCells=getNumberOfCells();
4134   const int *conn=_nodal_connec->getConstPointer();
4135   const int *connI=_nodal_connec_index->getConstPointer();
4136   double bb[2*SPACEDIM];
4137   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4138   for(int i=0;i<nbOfPoints;i++)
4139     {
4140       eltsIndex[i+1]=eltsIndex[i];
4141       for(int j=0;j<SPACEDIM;j++)
4142         {
4143           bb[2*j]=pos[SPACEDIM*i+j];
4144           bb[2*j+1]=pos[SPACEDIM*i+j];
4145         }
4146       std::vector<int> candidates;
4147       myTree.getIntersectingElems(bb,candidates);
4148       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4149         {
4150           int sz=connI[(*iter)+1]-connI[*iter]-1;
4151           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4152                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4153                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4154             {
4155               eltsIndex[i+1]++;
4156               elts.push_back(*iter);
4157             }
4158         }
4159     }
4160 }
4161 /*!
4162  * Finds cells in contact with several balls (i.e. points with precision).
4163  * This method is an extension of getCellContainingPoint() and
4164  * getCellsContainingPoint() for the case of multiple points.
4165  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4166  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4167  *         this->getSpaceDimension() * \a nbOfPoints 
4168  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4169  *  \param [in] eps - radius of balls (i.e. the precision).
4170  *  \param [in,out] elts - vector returning ids of found cells.
4171  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4172  *         dividing cell ids in \a elts into groups each referring to one
4173  *         point. Its every element (except the last one) is an index pointing to the
4174  *         first id of a group of cells. For example cells in contact with the *i*-th
4175  *         point are described by following range of indices:
4176  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4177  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4178  *         Number of cells in contact with the *i*-th point is
4179  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4180  *  \throw If the coordinates array is not set.
4181  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4182  *
4183  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4184  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4185  */
4186 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4187                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4188 {
4189   int spaceDim=getSpaceDimension();
4190   int mDim=getMeshDimension();
4191   if(spaceDim==3)
4192     {
4193       if(mDim==3)
4194         {
4195           const double *coords=_coords->getConstPointer();
4196           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4197         }
4198       /*else if(mDim==2)
4199         {
4200           
4201         }*/
4202       else
4203         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4204     }
4205   else if(spaceDim==2)
4206     {
4207       if(mDim==2)
4208         {
4209           const double *coords=_coords->getConstPointer();
4210           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4211         }
4212       else
4213         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4214     }
4215   else if(spaceDim==1)
4216     {
4217       if(mDim==1)
4218         {
4219           const double *coords=_coords->getConstPointer();
4220           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4221         }
4222       else
4223         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4224     }
4225   else
4226     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4227 }
4228
4229 /*!
4230  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4231  * least two its edges intersect each other anywhere except their extremities. An
4232  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4233  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4234  *         cleared before filling in.
4235  *  \param [in] eps - precision.
4236  *  \throw If \a this->getMeshDimension() != 2.
4237  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4238  */
4239 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4240 {
4241   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4242   if(getMeshDimension()!=2)
4243     throw INTERP_KERNEL::Exception(msg);
4244   int spaceDim=getSpaceDimension();
4245   if(spaceDim!=2 && spaceDim!=3)
4246     throw INTERP_KERNEL::Exception(msg);
4247   const int *conn=_nodal_connec->getConstPointer();
4248   const int *connI=_nodal_connec_index->getConstPointer();
4249   int nbOfCells=getNumberOfCells();
4250   std::vector<double> cell2DinS2;
4251   for(int i=0;i<nbOfCells;i++)
4252     {
4253       int offset=connI[i];
4254       int nbOfNodesForCell=connI[i+1]-offset-1;
4255       if(nbOfNodesForCell<=3)
4256         continue;
4257       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4258       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4259       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4260         cells.push_back(i);
4261       cell2DinS2.clear();
4262     }
4263 }
4264
4265 /*!
4266  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4267  *
4268  * 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.
4269  * 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.
4270  * 
4271  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4272  * This convex envelop is computed using Jarvis march algorithm.
4273  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4274  * 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)
4275  * 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.
4276  *
4277  * \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.
4278  */
4279 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4280 {
4281   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4282     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4283   checkFullyDefined();
4284   const double *coords=getCoords()->getConstPointer();
4285   int nbOfCells=getNumberOfCells();
4286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4287   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4289   int *workIndexOut=nodalConnecIndexOut->getPointer();
4290   *workIndexOut=0;
4291   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4292   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4293   std::set<INTERP_KERNEL::NormalizedCellType> types;
4294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4295   isChanged->alloc(0,1);
4296   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4297     {
4298       int pos=nodalConnecOut->getNumberOfTuples();
4299       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4300         isChanged->pushBackSilent(i);
4301       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4302       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4303     }
4304   if(isChanged->empty())
4305     return 0;
4306   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4307   _types=types;
4308   return isChanged.retn();
4309 }
4310
4311 /*!
4312  * This method is \b NOT const because it can modify \a this.
4313  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4314  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4315  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4316  * \b 1 for translation and rotation around point of 'mesh1D'.
4317  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4318  */
4319 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4320 {
4321   checkFullyDefined();
4322   mesh1D->checkFullyDefined();
4323   if(!mesh1D->isContiguous1D())
4324     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4325   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4326     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4327   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4328     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4329   if(mesh1D->getMeshDimension()!=1)
4330     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4331   bool isQuad=false;
4332   if(isPresenceOfQuadratic())
4333     {
4334       if(mesh1D->isFullyQuadratic())
4335         isQuad=true;
4336       else
4337         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4338     }
4339   zipCoords();
4340   int oldNbOfNodes=getNumberOfNodes();
4341   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4342   switch(policy)
4343     {
4344     case 0:
4345       {
4346         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4347         break;
4348       }
4349     case 1:
4350       {
4351         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4352         break;
4353       }
4354     default:
4355       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4356     }
4357   setCoords(newCoords);
4358   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4359   updateTime();
4360   return ret.retn();
4361 }
4362
4363 /*!
4364  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4365  * If it is not the case an exception will be thrown.
4366  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4367  * intersection of plane defined by ('origin','vec').
4368  * This method has one in/out parameter : 'cut3DCurve'.
4369  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4370  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4371  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4372  * This method will throw an exception if \a this contains a non linear segment.
4373  */
4374 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4375 {
4376   checkFullyDefined();
4377   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4378     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4379   int ncells=getNumberOfCells();
4380   int nnodes=getNumberOfNodes();
4381   double vec2[3],vec3[3],vec4[3];
4382   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4383   if(normm<1e-6)
4384     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4385   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4386   const int *conn=_nodal_connec->getConstPointer();
4387   const int *connI=_nodal_connec_index->getConstPointer();
4388   const double *coo=_coords->getConstPointer();
4389   std::vector<double> addCoo;
4390   for(int i=0;i<ncells;i++)
4391     {
4392       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4393         {
4394           if(cut3DCurve[i]==-2)
4395             {
4396               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4397               vec3[0]=coo[3*endd]-coo[3*st]; vec3[1]=coo[3*endd+1]-coo[3*st+1]; vec3[2]=coo[3*endd+2]-coo[3*st+2];
4398               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4399               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4400               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4401                 {
4402                   const double *st2=coo+3*st;
4403                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4404                   double pos=-(vec4[0]*vec2[0]+vec4[1]*vec2[1]+vec4[2]*vec2[2])/((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2]));
4405                   if(pos>eps && pos<1-eps)
4406                     {
4407                       int nNode=((int)addCoo.size())/3;
4408                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4409                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4410                       cut3DCurve[i]=nnodes+nNode;
4411                     }
4412                 }
4413             }
4414         }
4415       else
4416         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4417     }
4418   if(!addCoo.empty())
4419     {
4420       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4421       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4422       coo2->alloc(newNbOfNodes,3);
4423       double *tmp=coo2->getPointer();
4424       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4425       std::copy(addCoo.begin(),addCoo.end(),tmp);
4426       DataArrayDouble::SetArrayIn(coo2,_coords);
4427     }
4428 }
4429
4430 /*!
4431  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4432  * \param mesh1D is the input 1D mesh used for translation computation.
4433  * \return newCoords new coords filled by this method. 
4434  */
4435 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4436 {
4437   int oldNbOfNodes=getNumberOfNodes();
4438   int nbOf1DCells=mesh1D->getNumberOfCells();
4439   int spaceDim=getSpaceDimension();
4440   DataArrayDouble *ret=DataArrayDouble::New();
4441   std::vector<bool> isQuads;
4442   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4443   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4444   double *retPtr=ret->getPointer();
4445   const double *coords=getCoords()->getConstPointer();
4446   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4447   std::vector<int> v;
4448   std::vector<double> c;
4449   double vec[3];
4450   v.reserve(3);
4451   c.reserve(6);
4452   for(int i=0;i<nbOf1DCells;i++)
4453     {
4454       v.resize(0);
4455       mesh1D->getNodeIdsOfCell(i,v);
4456       c.resize(0);
4457       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4458       mesh1D->getCoordinatesOfNode(v[0],c);
4459       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4460       for(int j=0;j<oldNbOfNodes;j++)
4461         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4462       if(isQuad)
4463         {
4464           c.resize(0);
4465           mesh1D->getCoordinatesOfNode(v[1],c);
4466           mesh1D->getCoordinatesOfNode(v[0],c);
4467           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4468           for(int j=0;j<oldNbOfNodes;j++)
4469             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4470         }
4471     }
4472   ret->copyStringInfoFrom(*getCoords());
4473   return ret;
4474 }
4475
4476 /*!
4477  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4478  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4479  * \return newCoords new coords filled by this method. 
4480  */
4481 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4482 {
4483   if(mesh1D->getSpaceDimension()==2)
4484     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4485   if(mesh1D->getSpaceDimension()==3)
4486     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4487   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4488 }
4489
4490 /*!
4491  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4492  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4493  * \return newCoords new coords filled by this method. 
4494  */
4495 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4496 {
4497   if(isQuad)
4498     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4499   int oldNbOfNodes=getNumberOfNodes();
4500   int nbOf1DCells=mesh1D->getNumberOfCells();
4501   if(nbOf1DCells<2)
4502     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4503   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4504   int nbOfLevsInVec=nbOf1DCells+1;
4505   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4506   double *retPtr=ret->getPointer();
4507   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4508   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4509   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4510   tmp->setCoords(tmp2);
4511   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4512   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4513   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4514   for(int i=1;i<nbOfLevsInVec;i++)
4515     {
4516       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4517       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4518       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4519       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4520       tmp->translate(vec);
4521       double tmp3[2],radius,alpha,alpha0;
4522       const double *p0=i+1<nbOfLevsInVec?begin:third;
4523       const double *p1=i+1<nbOfLevsInVec?end:begin;
4524       const double *p2=i+1<nbOfLevsInVec?third:end;
4525       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4526       double cosangle=i+1<nbOfLevsInVec?(p0[0]-tmp3[0])*(p1[0]-tmp3[0])+(p0[1]-tmp3[1])*(p1[1]-tmp3[1]):(p2[0]-tmp3[0])*(p1[0]-tmp3[0])+(p2[1]-tmp3[1])*(p1[1]-tmp3[1]);
4527       double angle=acos(cosangle/(radius*radius));
4528       tmp->rotate(end,0,angle);
4529       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4530     }
4531   return ret.retn();
4532 }
4533
4534 /*!
4535  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4536  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4537  * \return newCoords new coords filled by this method. 
4538  */
4539 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4540 {
4541   if(isQuad)
4542     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4543   int oldNbOfNodes=getNumberOfNodes();
4544   int nbOf1DCells=mesh1D->getNumberOfCells();
4545   if(nbOf1DCells<2)
4546     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4547   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4548   int nbOfLevsInVec=nbOf1DCells+1;
4549   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4550   double *retPtr=ret->getPointer();
4551   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4552   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4553   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4554   tmp->setCoords(tmp2);
4555   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4556   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4557   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4558   for(int i=1;i<nbOfLevsInVec;i++)
4559     {
4560       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4561       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4562       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4563       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4564       tmp->translate(vec);
4565       double tmp3[2],radius,alpha,alpha0;
4566       const double *p0=i+1<nbOfLevsInVec?begin:third;
4567       const double *p1=i+1<nbOfLevsInVec?end:begin;
4568       const double *p2=i+1<nbOfLevsInVec?third:end;
4569       double vecPlane[3]={
4570         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4571         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4572         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4573       };
4574       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4575       if(norm>1.e-7)
4576         {
4577           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4578           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4579           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4580           double s2=norm2;
4581           double c2=cos(asin(s2));
4582           double m[3][3]={
4583             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4584             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4585             {-vec2[1]*s2, vec2[0]*s2, c2}
4586           };
4587           double p0r[3]={m[0][0]*p0[0]+m[0][1]*p0[1]+m[0][2]*p0[2], m[1][0]*p0[0]+m[1][1]*p0[1]+m[1][2]*p0[2], m[2][0]*p0[0]+m[2][1]*p0[1]+m[2][2]*p0[2]};
4588           double p1r[3]={m[0][0]*p1[0]+m[0][1]*p1[1]+m[0][2]*p1[2], m[1][0]*p1[0]+m[1][1]*p1[1]+m[1][2]*p1[2], m[2][0]*p1[0]+m[2][1]*p1[1]+m[2][2]*p1[2]};
4589           double p2r[3]={m[0][0]*p2[0]+m[0][1]*p2[1]+m[0][2]*p2[2], m[1][0]*p2[0]+m[1][1]*p2[1]+m[1][2]*p2[2], m[2][0]*p2[0]+m[2][1]*p2[1]+m[2][2]*p2[2]};
4590           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4591           double cosangle=i+1<nbOfLevsInVec?(p0r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p0r[1]-tmp3[1])*(p1r[1]-tmp3[1]):(p2r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p2r[1]-tmp3[1])*(p1r[1]-tmp3[1]);
4592           double angle=acos(cosangle/(radius*radius));
4593           tmp->rotate(end,vecPlane,angle);
4594           
4595         }
4596       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4597     }
4598   return ret.retn();
4599 }
4600
4601 /*!
4602  * This method is private because not easy to use for end user. This method is const contrary to
4603  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4604  * the coords sorted slice by slice.
4605  * \param isQuad specifies presence of quadratic cells.
4606  */
4607 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4608 {
4609   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4610   int nbOf2DCells=getNumberOfCells();
4611   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4612   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4613   const int *conn=_nodal_connec->getConstPointer();
4614   const int *connI=_nodal_connec_index->getConstPointer();
4615   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4616   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4617   newConnI->alloc(nbOf3DCells+1,1);
4618   int *newConnIPtr=newConnI->getPointer();
4619   *newConnIPtr++=0;
4620   std::vector<int> newc;
4621   for(int j=0;j<nbOf2DCells;j++)
4622     {
4623       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4624       *newConnIPtr++=(int)newc.size();
4625     }
4626   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4627   int *newConnPtr=newConn->getPointer();
4628   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4629   newConnIPtr=newConnI->getPointer();
4630   for(int iz=0;iz<nbOf1DCells;iz++)
4631     {
4632       if(iz!=0)
4633         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4634       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4635         {
4636           int icell=(int)(iter-newc.begin());
4637           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4638             {
4639               if(*iter!=-1)
4640                 *newConnPtr=(*iter)+iz*deltaPerLev;
4641               else
4642                 *newConnPtr=-1;
4643             }
4644           else
4645             *newConnPtr=(*iter);
4646         }
4647     }
4648   ret->setConnectivity(newConn,newConnI,true);
4649   ret->setCoords(getCoords());
4650   return ret;
4651 }
4652
4653 /*!
4654  * Checks if \a this mesh is constituted by only quadratic cells.
4655  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4656  *  \throw If the coordinates array is not set.
4657  *  \throw If the nodal connectivity of cells is not defined.
4658  */
4659 bool MEDCouplingUMesh::isFullyQuadratic() const
4660 {
4661   checkFullyDefined();
4662   bool ret=true;
4663   int nbOfCells=getNumberOfCells();
4664   for(int i=0;i<nbOfCells && ret;i++)
4665     {
4666       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4667       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4668       ret=cm.isQuadratic();
4669     }
4670   return ret;
4671 }
4672
4673 /*!
4674  * Checks if \a this mesh includes any quadratic cell.
4675  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4676  *  \throw If the coordinates array is not set.
4677  *  \throw If the nodal connectivity of cells is not defined.
4678  */
4679 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4680 {
4681   checkFullyDefined();
4682   bool ret=false;
4683   int nbOfCells=getNumberOfCells();
4684   for(int i=0;i<nbOfCells && !ret;i++)
4685     {
4686       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4687       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4688       ret=cm.isQuadratic();
4689     }
4690   return ret;
4691 }
4692
4693 /*!
4694  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4695  * this mesh, it remains unchanged.
4696  *  \throw If the coordinates array is not set.
4697  *  \throw If the nodal connectivity of cells is not defined.
4698  */
4699 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4700 {
4701   checkFullyDefined();
4702   int nbOfCells=getNumberOfCells();
4703   int delta=0;
4704   const int *iciptr=_nodal_connec_index->getConstPointer();
4705   for(int i=0;i<nbOfCells;i++)
4706     {
4707       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4708       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4709       if(cm.isQuadratic())
4710         {
4711           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4712           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4713           if(!cml.isDynamic())
4714             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4715           else
4716             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4717         }
4718     }
4719   if(delta==0)
4720     return ;
4721   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4722   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4723   const int *icptr=_nodal_connec->getConstPointer();
4724   newConn->alloc(getMeshLength()-delta,1);
4725   newConnI->alloc(nbOfCells+1,1);
4726   int *ocptr=newConn->getPointer();
4727   int *ociptr=newConnI->getPointer();
4728   *ociptr=0;
4729   _types.clear();
4730   for(int i=0;i<nbOfCells;i++,ociptr++)
4731     {
4732       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4733       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4734       if(!cm.isQuadratic())
4735         {
4736           _types.insert(type);
4737           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4738           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4739         }
4740       else
4741         {
4742           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4743           _types.insert(typel);
4744           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4745           int newNbOfNodes=cml.getNumberOfNodes();
4746           if(cml.isDynamic())
4747             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4748           *ocptr++=(int)typel;
4749           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4750           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4751         }
4752     }
4753   setConnectivity(newConn,newConnI,false);
4754 }
4755
4756 /*!
4757  * This method converts all linear cell in \a this to quadratic one.
4758  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4759  * 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)
4760  * 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.
4761  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4762  * end of the existing coordinates.
4763  * 
4764  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4765  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4766  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4767  * 
4768  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4769  *
4770  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4771  */
4772 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4773 {
4774   DataArrayInt *conn=0,*connI=0;
4775   DataArrayDouble *coords=0;
4776   std::set<INTERP_KERNEL::NormalizedCellType> types;
4777   checkFullyDefined();
4778   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4779   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4780   int meshDim=getMeshDimension();
4781   switch(conversionType)
4782     {
4783     case 0:
4784       switch(meshDim)
4785         {
4786         case 1:
4787           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4788           connSafe=conn; connISafe=connI; coordsSafe=coords;
4789           break;
4790         case 2:
4791           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4792           connSafe=conn; connISafe=connI; coordsSafe=coords;
4793           break;
4794         case 3:
4795           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4796           connSafe=conn; connISafe=connI; coordsSafe=coords;
4797           break;
4798         default:
4799           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4800         }
4801       break;
4802     case 1:
4803       {
4804         switch(meshDim)
4805         {
4806         case 1:
4807           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4808           connSafe=conn; connISafe=connI; coordsSafe=coords;
4809           break;
4810         case 2:
4811           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4812           connSafe=conn; connISafe=connI; coordsSafe=coords;
4813           break;
4814         case 3:
4815           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4816           connSafe=conn; connISafe=connI; coordsSafe=coords;
4817           break;
4818         default:
4819           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4820         }
4821         break;
4822       }
4823     default:
4824       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4825     }
4826   setConnectivity(connSafe,connISafe,false);
4827   _types=types;
4828   setCoords(coordsSafe);
4829   return ret.retn();
4830 }
4831
4832 /*!
4833  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4834  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4835  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4836  */
4837 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4838 {
4839   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4842   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4843   int nbOfCells=getNumberOfCells();
4844   int nbOfNodes=getNumberOfNodes();
4845   const int *cPtr=_nodal_connec->getConstPointer();
4846   const int *icPtr=_nodal_connec_index->getConstPointer();
4847   int lastVal=0,offset=nbOfNodes;
4848   for(int i=0;i<nbOfCells;i++,icPtr++)
4849     {
4850       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4851       if(type==INTERP_KERNEL::NORM_SEG2)
4852         {
4853           types.insert(INTERP_KERNEL::NORM_SEG3);
4854           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4855           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4856           newConn->pushBackSilent(offset++);
4857           lastVal+=4;
4858           newConnI->pushBackSilent(lastVal);
4859           ret->pushBackSilent(i);
4860         }
4861       else
4862         {
4863           types.insert(type);
4864           lastVal+=(icPtr[1]-icPtr[0]);
4865           newConnI->pushBackSilent(lastVal);
4866           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4867         }
4868     }
4869   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4870   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4871   return ret.retn();
4872 }
4873
4874 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4875 {
4876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4879   //
4880   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4881   DataArrayInt *conn1D=0,*conn1DI=0;
4882   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4883   DataArrayDouble *coordsTmp=0;
4884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4885   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4886   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4887   const int *c1DPtr=conn1D->begin();
4888   const int *c1DIPtr=conn1DI->begin();
4889   int nbOfCells=getNumberOfCells();
4890   const int *cPtr=_nodal_connec->getConstPointer();
4891   const int *icPtr=_nodal_connec_index->getConstPointer();
4892   int lastVal=0;
4893   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4894     {
4895       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4896       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4897       if(!cm.isQuadratic())
4898         {
4899           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4900           types.insert(typ2); newConn->pushBackSilent(typ2);
4901           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4902           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4903             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4904           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4905           newConnI->pushBackSilent(lastVal);
4906           ret->pushBackSilent(i);
4907         }
4908       else
4909         {
4910           types.insert(typ);
4911           lastVal+=(icPtr[1]-icPtr[0]);
4912           newConnI->pushBackSilent(lastVal);
4913           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4914         }
4915     }
4916   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4917   return ret.retn();
4918 }
4919
4920 /*!
4921  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4922  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4923  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4924  */
4925 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4926 {
4927   
4928   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4929   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4930   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4931 }
4932
4933 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4934 {
4935   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4936   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4937   //
4938   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4939   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4940   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4941   //
4942   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4943   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4944   DataArrayInt *conn1D=0,*conn1DI=0;
4945   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4946   DataArrayDouble *coordsTmp=0;
4947   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4948   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4949   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4950   const int *c1DPtr=conn1D->begin();
4951   const int *c1DIPtr=conn1DI->begin();
4952   int nbOfCells=getNumberOfCells();
4953   const int *cPtr=_nodal_connec->getConstPointer();
4954   const int *icPtr=_nodal_connec_index->getConstPointer();
4955   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4956   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4957     {
4958       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4959       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4960       if(!cm.isQuadratic())
4961         {
4962           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4963           types.insert(typ2); newConn->pushBackSilent(typ2);
4964           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4965           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4966             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4967           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4968           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
4969           newConnI->pushBackSilent(lastVal);
4970           ret->pushBackSilent(i);
4971         }
4972       else
4973         {
4974           types.insert(typ);
4975           lastVal+=(icPtr[1]-icPtr[0]);
4976           newConnI->pushBackSilent(lastVal);
4977           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4978         }
4979     }
4980   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4981   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
4982   return ret.retn();
4983 }
4984
4985 /*!
4986  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4987  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4988  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4989  */
4990 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4991 {
4992   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4993   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4994   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4995 }
4996
4997 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4998 {
4999   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5000   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5001   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5002   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5003   //
5004   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5005   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5006   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5007   //
5008   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5009   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5010   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5011   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5012   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5013   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5015   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5017   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5018   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5019   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5020   int nbOfCells=getNumberOfCells();
5021   const int *cPtr=_nodal_connec->getConstPointer();
5022   const int *icPtr=_nodal_connec_index->getConstPointer();
5023   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5024   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5025     {
5026       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5027       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5028       if(!cm.isQuadratic())
5029         {
5030           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5031           if(typ2==INTERP_KERNEL::NORM_ERROR)
5032             {
5033               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5034               throw INTERP_KERNEL::Exception(oss.str().c_str());
5035             }
5036           types.insert(typ2); newConn->pushBackSilent(typ2);
5037           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5038           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5039             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5040           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5041             {
5042               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5043               int tmpPos=newConn->getNumberOfTuples();
5044               newConn->pushBackSilent(nodeId2);
5045               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5046             }
5047           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5048           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5049           newConnI->pushBackSilent(lastVal);
5050           ret->pushBackSilent(i);
5051         }
5052       else
5053         {
5054           types.insert(typ);
5055           lastVal+=(icPtr[1]-icPtr[0]);
5056           newConnI->pushBackSilent(lastVal);
5057           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5058         }
5059     }
5060   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5061   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5062   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5063   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5064   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5065   int *c=newConn->getPointer();
5066   const int *cI(newConnI->begin());
5067   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5068     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5069   offset=coordsTmp2Safe->getNumberOfTuples();
5070   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5071     c[cI[(*elt)+1]-1]+=offset;
5072   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5073   return ret.retn();
5074 }
5075
5076 /*!
5077  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5078  * so that the number of cells remains the same. Quadratic faces are converted to
5079  * polygons. This method works only for 2D meshes in
5080  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5081  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5082  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5083  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5084  *         a polylinized edge constituting the input polygon.
5085  *  \throw If the coordinates array is not set.
5086  *  \throw If the nodal connectivity of cells is not defined.
5087  *  \throw If \a this->getMeshDimension() != 2.
5088  *  \throw If \a this->getSpaceDimension() != 2.
5089  */
5090 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5091 {
5092   checkFullyDefined();
5093   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5095   double epsa=fabs(eps);
5096   if(epsa<std::numeric_limits<double>::min())
5097     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5099   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5100   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5101   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5103   revDesc1=0; revDescIndx1=0;
5104   mDesc->tessellate2DCurve(eps);
5105   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5106   setCoords(mDesc->getCoords());
5107 }
5108
5109 /*!
5110  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5111  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5112  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5113  *         a sub-divided edge.
5114  *  \throw If the coordinates array is not set.
5115  *  \throw If the nodal connectivity of cells is not defined.
5116  *  \throw If \a this->getMeshDimension() != 1.
5117  *  \throw If \a this->getSpaceDimension() != 2.
5118  */
5119 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5120 {
5121   checkFullyDefined();
5122   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5123     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5124   double epsa=fabs(eps);
5125   if(epsa<std::numeric_limits<double>::min())
5126     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5127   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5128   int nbCells=getNumberOfCells();
5129   int nbNodes=getNumberOfNodes();
5130   const int *conn=_nodal_connec->getConstPointer();
5131   const int *connI=_nodal_connec_index->getConstPointer();
5132   const double *coords=_coords->getConstPointer();
5133   std::vector<double> addCoo;
5134   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5136   newConnI->alloc(nbCells+1,1);
5137   int *newConnIPtr=newConnI->getPointer();
5138   *newConnIPtr=0;
5139   int tmp1[3];
5140   INTERP_KERNEL::Node *tmp2[3];
5141   std::set<INTERP_KERNEL::NormalizedCellType> types;
5142   for(int i=0;i<nbCells;i++,newConnIPtr++)
5143     {
5144       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5145       if(cm.isQuadratic())
5146         {//assert(connI[i+1]-connI[i]-1==3)
5147           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5148           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5149           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5150           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5151           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5152           if(eac)
5153             {
5154               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5155               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5156               delete eac;
5157               newConnIPtr[1]=(int)newConn.size();
5158             }
5159           else
5160             {
5161               types.insert(INTERP_KERNEL::NORM_SEG2);
5162               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5163               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5164               newConnIPtr[1]=newConnIPtr[0]+3;
5165             }
5166         }
5167       else
5168         {
5169           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5170           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5171           newConnIPtr[1]=newConnIPtr[0]+3;
5172         }
5173     }
5174   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5175     return ;
5176   _types=types;
5177   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5179   newConnArr->alloc((int)newConn.size(),1);
5180   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5181   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5182   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5183   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5184   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5185   std::copy(addCoo.begin(),addCoo.end(),work);
5186   DataArrayDouble::SetArrayIn(newCoords,_coords);
5187   updateTime();
5188 }
5189
5190 /*!
5191  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5192  * In addition, returns an array mapping new cells to old ones. <br>
5193  * This method typically increases the number of cells in \a this mesh
5194  * but the number of nodes remains \b unchanged.
5195  * That's why the 3D splitting policies
5196  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5197  *  \param [in] policy - specifies a pattern used for splitting.
5198  * The semantic of \a policy is:
5199  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5200  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5201  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5202  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5203  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5204  *          an id of old cell producing it. The caller is to delete this array using
5205  *         decrRef() as it is no more needed. 
5206  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5207  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5208  *          and \a this->getMeshDimension() != 3. 
5209  *  \throw If \a policy is not one of the four discussed above.
5210  *  \throw If the nodal connectivity of cells is not defined.
5211  */
5212 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5213 {
5214   switch(policy)
5215     {
5216     case 0:
5217       return simplexizePol0();
5218     case 1:
5219       return simplexizePol1();
5220     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5221       return simplexizePlanarFace5();
5222     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5223       return simplexizePlanarFace6();
5224     default:
5225       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)");
5226     }
5227 }
5228
5229 /*!
5230  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5231  * - 1D: INTERP_KERNEL::NORM_SEG2
5232  * - 2D: INTERP_KERNEL::NORM_TRI3
5233  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5234  *
5235  * This method is useful for users that need to use P1 field services as
5236  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5237  * All these methods need mesh support containing only simplex cells.
5238  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5239  *  \throw If the coordinates array is not set.
5240  *  \throw If the nodal connectivity of cells is not defined.
5241  *  \throw If \a this->getMeshDimension() < 1.
5242  */
5243 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5244 {
5245   checkFullyDefined();
5246   int mdim=getMeshDimension();
5247   if(mdim<1 || mdim>3)
5248     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5249   int nbCells=getNumberOfCells();
5250   const int *conn=_nodal_connec->getConstPointer();
5251   const int *connI=_nodal_connec_index->getConstPointer();
5252   for(int i=0;i<nbCells;i++)
5253     {
5254       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5255       if(!cm.isSimplex())
5256         return false;
5257     }
5258   return true;
5259 }
5260
5261 /*!
5262  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5263  */
5264 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5265 {
5266   checkConnectivityFullyDefined();
5267   if(getMeshDimension()!=2)
5268     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5269   int nbOfCells=getNumberOfCells();
5270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5271   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5272   ret->alloc(nbOfCells+nbOfCutCells,1);
5273   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5274   int *retPt=ret->getPointer();
5275   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5277   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5278   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5279   int *pt=newConn->getPointer();
5280   int *ptI=newConnI->getPointer();
5281   ptI[0]=0;
5282   const int *oldc=_nodal_connec->getConstPointer();
5283   const int *ci=_nodal_connec_index->getConstPointer();
5284   for(int i=0;i<nbOfCells;i++,ci++)
5285     {
5286       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5287         {
5288           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5289                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5290           pt=std::copy(tmp,tmp+8,pt);
5291           ptI[1]=ptI[0]+4;
5292           ptI[2]=ptI[0]+8;
5293           *retPt++=i;
5294           *retPt++=i;
5295           ptI+=2;
5296         }
5297       else
5298         {
5299           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5300           ptI[1]=ptI[0]+ci[1]-ci[0];
5301           ptI++;
5302           *retPt++=i;
5303         }
5304     }
5305   _nodal_connec->decrRef();
5306   _nodal_connec=newConn.retn();
5307   _nodal_connec_index->decrRef();
5308   _nodal_connec_index=newConnI.retn();
5309   computeTypes();
5310   updateTime();
5311   return ret.retn();
5312 }
5313
5314 /*!
5315  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5316  */
5317 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5318 {
5319   checkConnectivityFullyDefined();
5320   if(getMeshDimension()!=2)
5321     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5322   int nbOfCells=getNumberOfCells();
5323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5324   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5325   ret->alloc(nbOfCells+nbOfCutCells,1);
5326   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5327   int *retPt=ret->getPointer();
5328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5330   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5331   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5332   int *pt=newConn->getPointer();
5333   int *ptI=newConnI->getPointer();
5334   ptI[0]=0;
5335   const int *oldc=_nodal_connec->getConstPointer();
5336   const int *ci=_nodal_connec_index->getConstPointer();
5337   for(int i=0;i<nbOfCells;i++,ci++)
5338     {
5339       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5340         {
5341           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5342                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5343           pt=std::copy(tmp,tmp+8,pt);
5344           ptI[1]=ptI[0]+4;
5345           ptI[2]=ptI[0]+8;
5346           *retPt++=i;
5347           *retPt++=i;
5348           ptI+=2;
5349         }
5350       else
5351         {
5352           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5353           ptI[1]=ptI[0]+ci[1]-ci[0];
5354           ptI++;
5355           *retPt++=i;
5356         }
5357     }
5358   _nodal_connec->decrRef();
5359   _nodal_connec=newConn.retn();
5360   _nodal_connec_index->decrRef();
5361   _nodal_connec_index=newConnI.retn();
5362   computeTypes();
5363   updateTime();
5364   return ret.retn();
5365 }
5366
5367 /*!
5368  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5369  */
5370 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5371 {
5372   checkConnectivityFullyDefined();
5373   if(getMeshDimension()!=3)
5374     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5375   int nbOfCells=getNumberOfCells();
5376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5377   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5378   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5379   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5380   int *retPt=ret->getPointer();
5381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5382   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5383   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5384   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5385   int *pt=newConn->getPointer();
5386   int *ptI=newConnI->getPointer();
5387   ptI[0]=0;
5388   const int *oldc=_nodal_connec->getConstPointer();
5389   const int *ci=_nodal_connec_index->getConstPointer();
5390   for(int i=0;i<nbOfCells;i++,ci++)
5391     {
5392       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5393         {
5394           for(int j=0;j<5;j++,pt+=5,ptI++)
5395             {
5396               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5397               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+3]+1];
5398               *retPt++=i;
5399               ptI[1]=ptI[0]+5;
5400             }
5401         }
5402       else
5403         {
5404           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5405           ptI[1]=ptI[0]+ci[1]-ci[0];
5406           ptI++;
5407           *retPt++=i;
5408         }
5409     }
5410   _nodal_connec->decrRef();
5411   _nodal_connec=newConn.retn();
5412   _nodal_connec_index->decrRef();
5413   _nodal_connec_index=newConnI.retn();
5414   computeTypes();
5415   updateTime();
5416   return ret.retn();
5417 }
5418
5419 /*!
5420  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5421  */
5422 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5423 {
5424   checkConnectivityFullyDefined();
5425   if(getMeshDimension()!=3)
5426     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5427   int nbOfCells=getNumberOfCells();
5428   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5429   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5430   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5431   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5432   int *retPt=ret->getPointer();
5433   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5434   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5435   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5436   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5437   int *pt=newConn->getPointer();
5438   int *ptI=newConnI->getPointer();
5439   ptI[0]=0;
5440   const int *oldc=_nodal_connec->getConstPointer();
5441   const int *ci=_nodal_connec_index->getConstPointer();
5442   for(int i=0;i<nbOfCells;i++,ci++)
5443     {
5444       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5445         {
5446           for(int j=0;j<6;j++,pt+=5,ptI++)
5447             {
5448               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5449               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+3]+1];
5450               *retPt++=i;
5451               ptI[1]=ptI[0]+5;
5452             }
5453         }
5454       else
5455         {
5456           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5457           ptI[1]=ptI[0]+ci[1]-ci[0];
5458           ptI++;
5459           *retPt++=i;
5460         }
5461     }
5462   _nodal_connec->decrRef();
5463   _nodal_connec=newConn.retn();
5464   _nodal_connec_index->decrRef();
5465   _nodal_connec_index=newConnI.retn();
5466   computeTypes();
5467   updateTime();
5468   return ret.retn();
5469 }
5470
5471 /*!
5472  * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5473  * This method completly ignore coordinates.
5474  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5475  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5476  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5477  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5478  */
5479 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5480 {
5481   checkFullyDefined();
5482   if(getMeshDimension()!=2)
5483     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5484   int nbOfCells=getNumberOfCells();
5485   int *connI=_nodal_connec_index->getPointer();
5486   int newConnLgth=0;
5487   for(int i=0;i<nbOfCells;i++,connI++)
5488     {
5489       int offset=descIndex[i];
5490       int nbOfEdges=descIndex[i+1]-offset;
5491       //
5492       bool ddirect=desc[offset+nbOfEdges-1]>0;
5493       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5494       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5495       for(int j=0;j<nbOfEdges;j++)
5496         {
5497           bool direct=desc[offset+j]>0;
5498           int edgeId=std::abs(desc[offset+j])-1;
5499           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5500             {
5501               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5502               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5503               int ref2=direct?id1:id2;
5504               if(ref==ref2)
5505                 {
5506                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5507                   newConnLgth+=nbOfSubNodes-1;
5508                   ref=direct?id2:id1;
5509                 }
5510               else
5511                 {
5512                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5513                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5514                 }
5515             }
5516           else
5517             {
5518               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5519             }
5520         }
5521       newConnLgth++;//+1 is for cell type
5522       connI[1]=newConnLgth;
5523     }
5524   //
5525   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5526   newConn->alloc(newConnLgth,1);
5527   int *work=newConn->getPointer();
5528   for(int i=0;i<nbOfCells;i++)
5529     {
5530       *work++=INTERP_KERNEL::NORM_POLYGON;
5531       int offset=descIndex[i];
5532       int nbOfEdges=descIndex[i+1]-offset;
5533       for(int j=0;j<nbOfEdges;j++)
5534         {
5535           bool direct=desc[offset+j]>0;
5536           int edgeId=std::abs(desc[offset+j])-1;
5537           if(direct)
5538             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5539           else
5540             {
5541               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5542               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5543               work=std::copy(it,it+nbOfSubNodes-1,work);
5544             }
5545         }
5546     }
5547   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5548   _types.clear();
5549   if(nbOfCells>0)
5550     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5551 }
5552
5553 /*!
5554  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5555  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5556  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5557  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5558  * so it can be useful to call mergeNodes() before calling this method.
5559  *  \throw If \a this->getMeshDimension() <= 1.
5560  *  \throw If the coordinates array is not set.
5561  *  \throw If the nodal connectivity of cells is not defined.
5562  */
5563 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5564 {
5565   checkFullyDefined();
5566   if(getMeshDimension()<=1)
5567     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5568   int nbOfCells=getNumberOfCells();
5569   if(nbOfCells<1)
5570     return ;
5571   int initMeshLgth=getMeshLength();
5572   int *conn=_nodal_connec->getPointer();
5573   int *index=_nodal_connec_index->getPointer();
5574   int posOfCurCell=0;
5575   int newPos=0;
5576   int lgthOfCurCell;
5577   for(int i=0;i<nbOfCells;i++)
5578     {
5579       lgthOfCurCell=index[i+1]-posOfCurCell;
5580       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5581       int newLgth;
5582       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5583                                                                                                      conn+newPos+1,newLgth);
5584       conn[newPos]=newType;
5585       newPos+=newLgth+1;
5586       posOfCurCell=index[i+1];
5587       index[i+1]=newPos;
5588     }
5589   if(newPos!=initMeshLgth)
5590     _nodal_connec->reAlloc(newPos);
5591   computeTypes();
5592 }
5593
5594 /*!
5595  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5596  * A cell is considered to be oriented correctly if an angle between its
5597  * normal vector and a given vector is less than \c PI / \c 2.
5598  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5599  *         cells. 
5600  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5601  *         checked.
5602  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5603  *         is not cleared before filling in.
5604  *  \throw If \a this->getMeshDimension() != 2.
5605  *  \throw If \a this->getSpaceDimension() != 3.
5606  *
5607  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5608  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5609  */
5610 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5611 {
5612   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5613     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5614   int nbOfCells=getNumberOfCells();
5615   const int *conn=_nodal_connec->getConstPointer();
5616   const int *connI=_nodal_connec_index->getConstPointer();
5617   const double *coordsPtr=_coords->getConstPointer();
5618   for(int i=0;i<nbOfCells;i++)
5619     {
5620       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5621       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5622         {
5623           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5624           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5625             cells.push_back(i);
5626         }
5627     }
5628 }
5629
5630 /*!
5631  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5632  * considered to be oriented correctly if an angle between its normal vector and a
5633  * given vector is less than \c PI / \c 2. 
5634  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5635  *         cells. 
5636  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5637  *         checked.
5638  *  \throw If \a this->getMeshDimension() != 2.
5639  *  \throw If \a this->getSpaceDimension() != 3.
5640  *
5641  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5642  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5643  */
5644 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5645 {
5646   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5647     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5648   int nbOfCells=getNumberOfCells();
5649   int *conn=_nodal_connec->getPointer();
5650   const int *connI=_nodal_connec_index->getConstPointer();
5651   const double *coordsPtr=_coords->getConstPointer();
5652   bool isModified=false;
5653   for(int i=0;i<nbOfCells;i++)
5654     {
5655       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5656       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5657         {
5658           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5659           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5660             {
5661               isModified=true;
5662               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5663               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5664               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5665             }
5666         }
5667     }
5668   if(isModified)
5669     _nodal_connec->declareAsNew();
5670   updateTime();
5671 }
5672
5673 /*!
5674  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5675  * oriented facets. The normal vector of the facet should point out of the cell.
5676  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5677  *         is not cleared before filling in.
5678  *  \throw If \a this->getMeshDimension() != 3.
5679  *  \throw If \a this->getSpaceDimension() != 3.
5680  *  \throw If the coordinates array is not set.
5681  *  \throw If the nodal connectivity of cells is not defined.
5682  *
5683  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5684  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5685  */
5686 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5687 {
5688   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5689     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5690   int nbOfCells=getNumberOfCells();
5691   const int *conn=_nodal_connec->getConstPointer();
5692   const int *connI=_nodal_connec_index->getConstPointer();
5693   const double *coordsPtr=_coords->getConstPointer();
5694   for(int i=0;i<nbOfCells;i++)
5695     {
5696       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5697       if(type==INTERP_KERNEL::NORM_POLYHED)
5698         {
5699           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5700             cells.push_back(i);
5701         }
5702     }
5703 }
5704
5705 /*!
5706  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5707  * out of the cell. 
5708  *  \throw If \a this->getMeshDimension() != 3.
5709  *  \throw If \a this->getSpaceDimension() != 3.
5710  *  \throw If the coordinates array is not set.
5711  *  \throw If the nodal connectivity of cells is not defined.
5712  *  \throw If the reparation fails.
5713  *
5714  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5715  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5716  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5717  */
5718 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5719 {
5720   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5721     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5722   int nbOfCells=getNumberOfCells();
5723   int *conn=_nodal_connec->getPointer();
5724   const int *connI=_nodal_connec_index->getConstPointer();
5725   const double *coordsPtr=_coords->getConstPointer();
5726   for(int i=0;i<nbOfCells;i++)
5727     {
5728       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5729       if(type==INTERP_KERNEL::NORM_POLYHED)
5730         {
5731           try
5732             {
5733               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5734                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5735             }
5736           catch(INTERP_KERNEL::Exception& e)
5737             {
5738               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5739               throw INTERP_KERNEL::Exception(oss.str().c_str());
5740             }
5741         }
5742     }
5743   updateTime();
5744 }
5745
5746 /*!
5747  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5748  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5749  * according to which the first facet of the cell should be oriented to have the normal vector
5750  * pointing out of cell.
5751  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5752  *         cells. The caller is to delete this array using decrRef() as it is no more
5753  *         needed. 
5754  *  \throw If \a this->getMeshDimension() != 3.
5755  *  \throw If \a this->getSpaceDimension() != 3.
5756  *  \throw If the coordinates array is not set.
5757  *  \throw If the nodal connectivity of cells is not defined.
5758  *
5759  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5760  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5761  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5762  */
5763 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5764 {
5765   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5766   if(getMeshDimension()!=3)
5767     throw INTERP_KERNEL::Exception(msg);
5768   int spaceDim=getSpaceDimension();
5769   if(spaceDim!=3)
5770     throw INTERP_KERNEL::Exception(msg);
5771   //
5772   int nbOfCells=getNumberOfCells();
5773   int *conn=_nodal_connec->getPointer();
5774   const int *connI=_nodal_connec_index->getConstPointer();
5775   const double *coo=getCoords()->getConstPointer();
5776   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5777   for(int i=0;i<nbOfCells;i++)
5778     {
5779       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5780       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5781         {
5782           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5783             {
5784               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5785               cells->pushBackSilent(i);
5786             }
5787         }
5788     }
5789   return cells.retn();
5790 }
5791
5792 /*!
5793  * This method is a faster method to correct orientation of all 3D cells in \a this.
5794  * 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.
5795  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5796  * 
5797  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5798  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5799  */
5800 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5801 {
5802   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5803     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5804   int nbOfCells=getNumberOfCells();
5805   int *conn=_nodal_connec->getPointer();
5806   const int *connI=_nodal_connec_index->getConstPointer();
5807   const double *coordsPtr=_coords->getConstPointer();
5808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5809   for(int i=0;i<nbOfCells;i++)
5810     {
5811       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5812       switch(type)
5813         {
5814         case INTERP_KERNEL::NORM_TETRA4:
5815           {
5816             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5817               {
5818                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5819                 ret->pushBackSilent(i);
5820               }
5821             break;
5822           }
5823         case INTERP_KERNEL::NORM_PYRA5:
5824           {
5825             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5826               {
5827                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5828                 ret->pushBackSilent(i);
5829               }
5830             break;
5831           }
5832         case INTERP_KERNEL::NORM_PENTA6:
5833         case INTERP_KERNEL::NORM_HEXA8:
5834         case INTERP_KERNEL::NORM_HEXGP12:
5835           {
5836             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5837               {
5838                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5839                 ret->pushBackSilent(i);
5840               }
5841             break;
5842           }
5843         case INTERP_KERNEL::NORM_POLYHED:
5844           {
5845             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5846               {
5847                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5848                 ret->pushBackSilent(i);
5849               }
5850             break;
5851           }
5852         default:
5853           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 !");
5854         }
5855     }
5856   updateTime();
5857   return ret.retn();
5858 }
5859
5860 /*!
5861  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5862  * If it is not the case an exception will be thrown.
5863  * This method is fast because the first cell of \a this is used to compute the plane.
5864  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5865  * \param pos output of size at least 3 used to store a point owned of searched plane.
5866  */
5867 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5868 {
5869   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5870     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5871   const int *conn=_nodal_connec->getConstPointer();
5872   const int *connI=_nodal_connec_index->getConstPointer();
5873   const double *coordsPtr=_coords->getConstPointer();
5874   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5875   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5876 }
5877
5878 /*!
5879  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5880  * cells. Currently cells of the following types are treated:
5881  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5882  * For a cell of other type an exception is thrown.
5883  * Space dimension of a 2D mesh can be either 2 or 3.
5884  * The Edge Ratio of a cell \f$t\f$ is: 
5885  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5886  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5887  *  the smallest edge lengths of \f$t\f$.
5888  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5889  *          cells and one time, lying on \a this mesh. The caller is to delete this
5890  *          field using decrRef() as it is no more needed. 
5891  *  \throw If the coordinates array is not set.
5892  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5893  *  \throw If the connectivity data array has more than one component.
5894  *  \throw If the connectivity data array has a named component.
5895  *  \throw If the connectivity index data array has more than one component.
5896  *  \throw If the connectivity index data array has a named component.
5897  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5898  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5899  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5900  */
5901 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5902 {
5903   checkCoherency();
5904   int spaceDim=getSpaceDimension();
5905   int meshDim=getMeshDimension();
5906   if(spaceDim!=2 && spaceDim!=3)
5907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5908   if(meshDim!=2 && meshDim!=3)
5909     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5910   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5911   ret->setMesh(this);
5912   int nbOfCells=getNumberOfCells();
5913   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5914   arr->alloc(nbOfCells,1);
5915   double *pt=arr->getPointer();
5916   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5917   const int *conn=_nodal_connec->getConstPointer();
5918   const int *connI=_nodal_connec_index->getConstPointer();
5919   const double *coo=_coords->getConstPointer();
5920   double tmp[12];
5921   for(int i=0;i<nbOfCells;i++,pt++)
5922     {
5923       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5924       switch(t)
5925         {
5926           case INTERP_KERNEL::NORM_TRI3:
5927             {
5928               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5929               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5930               break;
5931             }
5932           case INTERP_KERNEL::NORM_QUAD4:
5933             {
5934               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5935               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5936               break;
5937             }
5938           case INTERP_KERNEL::NORM_TETRA4:
5939             {
5940               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5941               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5942               break;
5943             }
5944         default:
5945           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5946         }
5947       conn+=connI[i+1]-connI[i];
5948     }
5949   ret->setName("EdgeRatio");
5950   ret->synchronizeTimeWithSupport();
5951   return ret.retn();
5952 }
5953
5954 /*!
5955  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5956  * cells. Currently cells of the following types are treated:
5957  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5958  * For a cell of other type an exception is thrown.
5959  * Space dimension of a 2D mesh can be either 2 or 3.
5960  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5961  *          cells and one time, lying on \a this mesh. The caller is to delete this
5962  *          field using decrRef() as it is no more needed. 
5963  *  \throw If the coordinates array is not set.
5964  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5965  *  \throw If the connectivity data array has more than one component.
5966  *  \throw If the connectivity data array has a named component.
5967  *  \throw If the connectivity index data array has more than one component.
5968  *  \throw If the connectivity index data array has a named component.
5969  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5970  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5971  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5972  */
5973 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
5974 {
5975   checkCoherency();
5976   int spaceDim=getSpaceDimension();
5977   int meshDim=getMeshDimension();
5978   if(spaceDim!=2 && spaceDim!=3)
5979     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5980   if(meshDim!=2 && meshDim!=3)
5981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5982   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5983   ret->setMesh(this);
5984   int nbOfCells=getNumberOfCells();
5985   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5986   arr->alloc(nbOfCells,1);
5987   double *pt=arr->getPointer();
5988   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5989   const int *conn=_nodal_connec->getConstPointer();
5990   const int *connI=_nodal_connec_index->getConstPointer();
5991   const double *coo=_coords->getConstPointer();
5992   double tmp[12];
5993   for(int i=0;i<nbOfCells;i++,pt++)
5994     {
5995       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5996       switch(t)
5997         {
5998           case INTERP_KERNEL::NORM_TRI3:
5999             {
6000               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6001               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6002               break;
6003             }
6004           case INTERP_KERNEL::NORM_QUAD4:
6005             {
6006               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6007               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6008               break;
6009             }
6010           case INTERP_KERNEL::NORM_TETRA4:
6011             {
6012               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6013               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6014               break;
6015             }
6016         default:
6017           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6018         }
6019       conn+=connI[i+1]-connI[i];
6020     }
6021   ret->setName("AspectRatio");
6022   ret->synchronizeTimeWithSupport();
6023   return ret.retn();
6024 }
6025
6026 /*!
6027  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6028  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6029  * treated: INTERP_KERNEL::NORM_QUAD4.
6030  * For a cell of other type an exception is thrown.
6031  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6032  *          cells and one time, lying on \a this mesh. The caller is to delete this
6033  *          field using decrRef() as it is no more needed. 
6034  *  \throw If the coordinates array is not set.
6035  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6036  *  \throw If the connectivity data array has more than one component.
6037  *  \throw If the connectivity data array has a named component.
6038  *  \throw If the connectivity index data array has more than one component.
6039  *  \throw If the connectivity index data array has a named component.
6040  *  \throw If \a this->getMeshDimension() != 2.
6041  *  \throw If \a this->getSpaceDimension() != 3.
6042  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6043  */
6044 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6045 {
6046   checkCoherency();
6047   int spaceDim=getSpaceDimension();
6048   int meshDim=getMeshDimension();
6049   if(spaceDim!=3)
6050     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6051   if(meshDim!=2)
6052     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6053   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6054   ret->setMesh(this);
6055   int nbOfCells=getNumberOfCells();
6056   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6057   arr->alloc(nbOfCells,1);
6058   double *pt=arr->getPointer();
6059   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6060   const int *conn=_nodal_connec->getConstPointer();
6061   const int *connI=_nodal_connec_index->getConstPointer();
6062   const double *coo=_coords->getConstPointer();
6063   double tmp[12];
6064   for(int i=0;i<nbOfCells;i++,pt++)
6065     {
6066       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6067       switch(t)
6068         {
6069           case INTERP_KERNEL::NORM_QUAD4:
6070             {
6071               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6072               *pt=INTERP_KERNEL::quadWarp(tmp);
6073               break;
6074             }
6075         default:
6076           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6077         }
6078       conn+=connI[i+1]-connI[i];
6079     }
6080   ret->setName("Warp");
6081   ret->synchronizeTimeWithSupport();
6082   return ret.retn();
6083 }
6084
6085
6086 /*!
6087  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6088  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6089  * treated: INTERP_KERNEL::NORM_QUAD4.
6090  * For a cell of other type an exception is thrown.
6091  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6092  *          cells and one time, lying on \a this mesh. The caller is to delete this
6093  *          field using decrRef() as it is no more needed. 
6094  *  \throw If the coordinates array is not set.
6095  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6096  *  \throw If the connectivity data array has more than one component.
6097  *  \throw If the connectivity data array has a named component.
6098  *  \throw If the connectivity index data array has more than one component.
6099  *  \throw If the connectivity index data array has a named component.
6100  *  \throw If \a this->getMeshDimension() != 2.
6101  *  \throw If \a this->getSpaceDimension() != 3.
6102  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6103  */
6104 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6105 {
6106   checkCoherency();
6107   int spaceDim=getSpaceDimension();
6108   int meshDim=getMeshDimension();
6109   if(spaceDim!=3)
6110     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6111   if(meshDim!=2)
6112     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6113   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6114   ret->setMesh(this);
6115   int nbOfCells=getNumberOfCells();
6116   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6117   arr->alloc(nbOfCells,1);
6118   double *pt=arr->getPointer();
6119   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6120   const int *conn=_nodal_connec->getConstPointer();
6121   const int *connI=_nodal_connec_index->getConstPointer();
6122   const double *coo=_coords->getConstPointer();
6123   double tmp[12];
6124   for(int i=0;i<nbOfCells;i++,pt++)
6125     {
6126       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6127       switch(t)
6128         {
6129           case INTERP_KERNEL::NORM_QUAD4:
6130             {
6131               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6132               *pt=INTERP_KERNEL::quadSkew(tmp);
6133               break;
6134             }
6135         default:
6136           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6137         }
6138       conn+=connI[i+1]-connI[i];
6139     }
6140   ret->setName("Skew");
6141   ret->synchronizeTimeWithSupport();
6142   return ret.retn();
6143 }
6144
6145 /*!
6146  * This method aggregate the bbox of each cell and put it into bbox parameter.
6147  * \param bbox out parameter of size 2*spacedim*nbOfcells.
6148  */
6149 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6150 {
6151   int spaceDim=getSpaceDimension();
6152   int nbOfCells=getNumberOfCells();
6153   bbox.resize(2*nbOfCells*spaceDim);
6154   for(int i=0;i<nbOfCells*spaceDim;i++)
6155     {
6156       bbox[2*i]=std::numeric_limits<double>::max();
6157       bbox[2*i+1]=-std::numeric_limits<double>::max();
6158     }
6159   const double *coordsPtr=_coords->getConstPointer();
6160   const int *conn=_nodal_connec->getConstPointer();
6161   const int *connI=_nodal_connec_index->getConstPointer();
6162   for(int i=0;i<nbOfCells;i++)
6163     {
6164       int offset=connI[i]+1;
6165       int nbOfNodesForCell=connI[i+1]-offset;
6166       for(int j=0;j<nbOfNodesForCell;j++)
6167         {
6168           int nodeId=conn[offset+j];
6169           if(nodeId>=0)
6170             for(int k=0;k<spaceDim;k++)
6171               {
6172                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6173                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6174               }
6175         }
6176     }
6177 }
6178
6179 /// @cond INTERNAL
6180
6181 namespace ParaMEDMEMImpl
6182 {
6183   class ConnReader
6184   {
6185   public:
6186     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6187     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6188   private:
6189     const int *_conn;
6190     int _val;
6191   };
6192
6193   class ConnReader2
6194   {
6195   public:
6196     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6197     bool operator() (const int& pos) { return _conn[pos]==_val; }
6198   private:
6199     const int *_conn;
6200     int _val;
6201   };
6202 }
6203
6204 /// @endcond
6205
6206 /*!
6207  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6208  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6209  * \a this is composed in cell types.
6210  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6211  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6212  * This parameter is kept only for compatibility with other methode listed above.
6213  */
6214 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6215 {
6216   checkConnectivityFullyDefined();
6217   const int *conn=_nodal_connec->getConstPointer();
6218   const int *connI=_nodal_connec_index->getConstPointer();
6219   const int *work=connI;
6220   int nbOfCells=getNumberOfCells();
6221   std::size_t n=getAllTypes().size();
6222   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6223   std::set<INTERP_KERNEL::NormalizedCellType> types;
6224   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6225     {
6226       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6227       if(types.find(typ)!=types.end())
6228         {
6229           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6230           oss << " is not contiguous !";
6231           throw INTERP_KERNEL::Exception(oss.str().c_str());
6232         }
6233       types.insert(typ);
6234       ret[3*i]=typ;
6235       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6236       ret[3*i+1]=(int)std::distance(work,work2);
6237       work=work2;
6238     }
6239   return ret;
6240 }
6241
6242 /*!
6243  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6244  * only for types cell, type node is not managed.
6245  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6246  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6247  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6248  * If 2 or more same geometric type is in \a code and exception is thrown too.
6249  *
6250  * This method firstly checks
6251  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6252  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6253  * an exception is thrown too.
6254  * 
6255  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6256  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6257  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6258  */
6259 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6260 {
6261   if(code.empty())
6262     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6263   std::size_t sz=code.size();
6264   std::size_t n=sz/3;
6265   if(sz%3!=0)
6266     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6267   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6268   int nb=0;
6269   bool isNoPflUsed=true;
6270   for(std::size_t i=0;i<n;i++)
6271     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6272       {
6273         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6274         nb+=code[3*i+1];
6275         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6276           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6277         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6278       }
6279   if(types.size()!=n)
6280     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6281   if(isNoPflUsed)
6282     {
6283       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6284         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6285       if(types.size()==_types.size())
6286         return 0;
6287     }
6288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6289   ret->alloc(nb,1);
6290   int *retPtr=ret->getPointer();
6291   const int *connI=_nodal_connec_index->getConstPointer();
6292   const int *conn=_nodal_connec->getConstPointer();
6293   int nbOfCells=getNumberOfCells();
6294   const int *i=connI;
6295   int kk=0;
6296   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6297     {
6298       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6299       int offset=(int)std::distance(connI,i);
6300       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6301       int nbOfCellsOfCurType=(int)std::distance(i,j);
6302       if(code[3*kk+2]==-1)
6303         for(int k=0;k<nbOfCellsOfCurType;k++)
6304           *retPtr++=k+offset;
6305       else
6306         {
6307           int idInIdsPerType=code[3*kk+2];
6308           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6309             {
6310               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6311               if(zePfl)
6312                 {
6313                   zePfl->checkAllocated();
6314                   if(zePfl->getNumberOfComponents()==1)
6315                     {
6316                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6317                         {
6318                           if(*k>=0 && *k<nbOfCellsOfCurType)
6319                             *retPtr=(*k)+offset;
6320                           else
6321                             {
6322                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6323                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6324                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6325                             }
6326                         }
6327                     }
6328                   else
6329                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6330                 }
6331               else
6332                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6333             }
6334           else
6335             {
6336               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6337               oss << " should be in [0," << idsPerType.size() << ") !";
6338               throw INTERP_KERNEL::Exception(oss.str().c_str());
6339             }
6340         }
6341       i=j;
6342     }
6343   return ret.retn();
6344 }
6345
6346 /*!
6347  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6348  * 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.
6349  * 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.
6350  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6351  * 
6352  * \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.
6353  * \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,
6354  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6355  * \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.
6356  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6357  * \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
6358  */
6359 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6360 {
6361   if(!profile)
6362     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6363   if(profile->getNumberOfComponents()!=1)
6364     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6365   checkConnectivityFullyDefined();
6366   const int *conn=_nodal_connec->getConstPointer();
6367   const int *connI=_nodal_connec_index->getConstPointer();
6368   int nbOfCells=getNumberOfCells();
6369   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6370   std::vector<int> typeRangeVals(1);
6371   for(const int *i=connI;i!=connI+nbOfCells;)
6372     {
6373       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6374       if(std::find(types.begin(),types.end(),curType)!=types.end())
6375         {
6376           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6377         }
6378       types.push_back(curType);
6379       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6380       typeRangeVals.push_back((int)std::distance(connI,i));
6381     }
6382   //
6383   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6384   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6385   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6386   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6388   //
6389   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6390   code.resize(3*nbOfCastsFinal);
6391   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6392   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6393   for(int i=0;i<nbOfCastsFinal;i++)
6394     {
6395       int castId=castsPresent->getIJ(i,0);
6396       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6397       idsInPflPerType2.push_back(tmp3);
6398       code[3*i]=(int)types[castId];
6399       code[3*i+1]=tmp3->getNumberOfTuples();
6400       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6401       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6402         {
6403           tmp4->copyStringInfoFrom(*profile);
6404           idsPerType2.push_back(tmp4);
6405           code[3*i+2]=(int)idsPerType2.size()-1;
6406         }
6407       else
6408         {
6409           code[3*i+2]=-1;
6410         }
6411     }
6412   std::size_t sz2=idsInPflPerType2.size();
6413   idsInPflPerType.resize(sz2);
6414   for(std::size_t i=0;i<sz2;i++)
6415     {
6416       DataArrayInt *locDa=idsInPflPerType2[i];
6417       locDa->incrRef();
6418       idsInPflPerType[i]=locDa;
6419     }
6420   std::size_t sz=idsPerType2.size();
6421   idsPerType.resize(sz);
6422   for(std::size_t i=0;i<sz;i++)
6423     {
6424       DataArrayInt *locDa=idsPerType2[i];
6425       locDa->incrRef();
6426       idsPerType[i]=locDa;
6427     }
6428 }
6429
6430 /*!
6431  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6432  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6433  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6434  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as ParaMEDMEM::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered.
6435  */
6436 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6437 {
6438   checkFullyDefined();
6439   nM1LevMesh->checkFullyDefined();
6440   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6441     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6442   if(_coords!=nM1LevMesh->getCoords())
6443     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6444   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6445   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6446   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6447   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6448   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6449   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6450   tmp->setConnectivity(tmp0,tmp1);
6451   tmp->renumberCells(ret0->getConstPointer(),false);
6452   revDesc=tmp->getNodalConnectivity();
6453   revDescIndx=tmp->getNodalConnectivityIndex();
6454   DataArrayInt *ret=0;
6455   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6456     {
6457       int tmp2;
6458       ret->getMaxValue(tmp2);
6459       ret->decrRef();
6460       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6461       throw INTERP_KERNEL::Exception(oss.str().c_str());
6462     }
6463   nM1LevMeshIds=ret;
6464   //
6465   revDesc->incrRef();
6466   revDescIndx->incrRef();
6467   ret1->incrRef();
6468   ret0->incrRef();
6469   meshnM1Old2New=ret0;
6470   return ret1;
6471 }
6472
6473 /*!
6474  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6475  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6476  * in "Old to New" mode.
6477  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6478  *          this array using decrRef() as it is no more needed.
6479  *  \throw If the nodal connectivity of cells is not defined.
6480  */
6481 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6482 {
6483   checkConnectivityFullyDefined();
6484   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6485   renumberCells(ret->getConstPointer(),false);
6486   return ret.retn();
6487 }
6488
6489 /*!
6490  * This methods checks that cells are sorted by their types.
6491  * This method makes asumption (no check) that connectivity is correctly set before calling.
6492  */
6493 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6494 {
6495   checkFullyDefined();
6496   const int *conn=_nodal_connec->getConstPointer();
6497   const int *connI=_nodal_connec_index->getConstPointer();
6498   int nbOfCells=getNumberOfCells();
6499   std::set<INTERP_KERNEL::NormalizedCellType> types;
6500   for(const int *i=connI;i!=connI+nbOfCells;)
6501     {
6502       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6503       if(types.find(curType)!=types.end())
6504         return false;
6505       types.insert(curType);
6506       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6507     }
6508   return true;
6509 }
6510
6511 /*!
6512  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6513  * The geometric type order is specified by MED file.
6514  * 
6515  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6516  */
6517 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6518 {
6519   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6520 }
6521
6522 /*!
6523  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6524  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6525  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6526  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6527  */
6528 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6529 {
6530   checkFullyDefined();
6531   const int *conn=_nodal_connec->getConstPointer();
6532   const int *connI=_nodal_connec_index->getConstPointer();
6533   int nbOfCells=getNumberOfCells();
6534   if(nbOfCells==0)
6535     return true;
6536   int lastPos=-1;
6537   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6538   for(const int *i=connI;i!=connI+nbOfCells;)
6539     {
6540       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6541       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6542       if(isTypeExists!=orderEnd)
6543         {
6544           int pos=(int)std::distance(orderBg,isTypeExists);
6545           if(pos<=lastPos)
6546             return false;
6547           lastPos=pos;
6548           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6549         }
6550       else
6551         {
6552           if(sg.find(curType)==sg.end())
6553             {
6554               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6555               sg.insert(curType);
6556             }
6557           else
6558             return false;
6559         }
6560     }
6561   return true;
6562 }
6563
6564 /*!
6565  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6566  * 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
6567  * 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'.
6568  */
6569 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6570 {
6571   checkConnectivityFullyDefined();
6572   int nbOfCells=getNumberOfCells();
6573   const int *conn=_nodal_connec->getConstPointer();
6574   const int *connI=_nodal_connec_index->getConstPointer();
6575   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6577   tmpa->alloc(nbOfCells,1);
6578   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6579   tmpb->fillWithZero();
6580   int *tmp=tmpa->getPointer();
6581   int *tmp2=tmpb->getPointer();
6582   for(const int *i=connI;i!=connI+nbOfCells;i++)
6583     {
6584       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6585       if(where!=orderEnd)
6586         {
6587           int pos=(int)std::distance(orderBg,where);
6588           tmp2[pos]++;
6589           tmp[std::distance(connI,i)]=pos;
6590         }
6591       else
6592         {
6593           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6594           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6595           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6596           throw INTERP_KERNEL::Exception(oss.str().c_str());
6597         }
6598     }
6599   nbPerType=tmpb.retn();
6600   return tmpa.retn();
6601 }
6602
6603 /*!
6604  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6605  *
6606  * \return a new object containing the old to new correspondance.
6607  *
6608  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6609  */
6610 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6611 {
6612   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6613 }
6614
6615 /*!
6616  * 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.
6617  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6618  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6619  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6620  */
6621 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6622 {
6623   DataArrayInt *nbPerType=0;
6624   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6625   nbPerType->decrRef();
6626   return tmpa->buildPermArrPerLevel();
6627 }
6628
6629 /*!
6630  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6631  * The number of cells remains unchanged after the call of this method.
6632  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6633  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6634  *
6635  * \return the array giving the correspondance old to new.
6636  */
6637 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6638 {
6639   checkFullyDefined();
6640   computeTypes();
6641   const int *conn=_nodal_connec->getConstPointer();
6642   const int *connI=_nodal_connec_index->getConstPointer();
6643   int nbOfCells=getNumberOfCells();
6644   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6645   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6646     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6647       {
6648         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6649         types.push_back(curType);
6650         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6651       }
6652   DataArrayInt *ret=DataArrayInt::New();
6653   ret->alloc(nbOfCells,1);
6654   int *retPtr=ret->getPointer();
6655   std::fill(retPtr,retPtr+nbOfCells,-1);
6656   int newCellId=0;
6657   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6658     {
6659       for(const int *i=connI;i!=connI+nbOfCells;i++)
6660         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6661           retPtr[std::distance(connI,i)]=newCellId++;
6662     }
6663   renumberCells(retPtr,false);
6664   return ret;
6665 }
6666
6667 /*!
6668  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6669  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6670  * This method makes asumption that connectivity is correctly set before calling.
6671  */
6672 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6673 {
6674   checkConnectivityFullyDefined();
6675   const int *conn=_nodal_connec->getConstPointer();
6676   const int *connI=_nodal_connec_index->getConstPointer();
6677   int nbOfCells=getNumberOfCells();
6678   std::vector<MEDCouplingUMesh *> ret;
6679   for(const int *i=connI;i!=connI+nbOfCells;)
6680     {
6681       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6682       int beginCellId=(int)std::distance(connI,i);
6683       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6684       int endCellId=(int)std::distance(connI,i);
6685       int sz=endCellId-beginCellId;
6686       int *cells=new int[sz];
6687       for(int j=0;j<sz;j++)
6688         cells[j]=beginCellId+j;
6689       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6690       delete [] cells;
6691       ret.push_back(m);
6692     }
6693   return ret;
6694 }
6695
6696 /*!
6697  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6698  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6699  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6700  *
6701  * \return a newly allocated instance, that the caller must manage.
6702  * \throw If \a this contains more than one geometric type.
6703  * \throw If the nodal connectivity of \a this is not fully defined.
6704  * \throw If the internal data is not coherent.
6705  */
6706 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6707 {
6708   checkConnectivityFullyDefined();
6709     if(_types.size()!=1)
6710     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6711   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6712   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6713   ret->setCoords(getCoords());
6714   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6715   if(retC)
6716     {
6717       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6718       retC->setNodalConnectivity(c);
6719     }
6720   else
6721     {
6722       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6723       if(!retD)
6724         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6725       DataArrayInt *c=0,*ci=0;
6726       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6727       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6728       retD->setNodalConnectivity(cs,cis);
6729     }
6730   return ret.retn();
6731 }
6732
6733 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6734 {
6735   checkConnectivityFullyDefined();
6736     if(_types.size()!=1)
6737     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6738   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6739   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6740   if(cm.isDynamic())
6741     {
6742       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6743       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6744       throw INTERP_KERNEL::Exception(oss.str().c_str());
6745     }
6746   int nbCells=getNumberOfCells();
6747   int typi=(int)typ;
6748   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6749   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6750   int *outPtr=connOut->getPointer();
6751   const int *conn=_nodal_connec->begin();
6752   const int *connI=_nodal_connec_index->begin();
6753   nbNodesPerCell++;
6754   for(int i=0;i<nbCells;i++,connI++)
6755     {
6756       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6757         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6758       else
6759         {
6760           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 << ") !";
6761           throw INTERP_KERNEL::Exception(oss.str().c_str());
6762         }
6763     }
6764   return connOut.retn();
6765 }
6766
6767 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6768 {
6769   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6770   checkConnectivityFullyDefined();
6771   if(_types.size()!=1)
6772     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6773   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6774   if(lgth<nbCells)
6775     throw INTERP_KERNEL::Exception(msg0);
6776   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6777   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6778   int *cp(c->getPointer()),*cip(ci->getPointer());
6779   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6780   cip[0]=0;
6781   for(int i=0;i<nbCells;i++,cip++,incip++)
6782     {
6783       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6784       int delta(stop-strt);
6785       if(delta>=1)
6786         {
6787           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6788             cp=std::copy(incp+strt,incp+stop,cp);
6789           else
6790             throw INTERP_KERNEL::Exception(msg0);
6791         }
6792       else
6793         throw INTERP_KERNEL::Exception(msg0);
6794       cip[1]=cip[0]+delta;
6795     }
6796   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6797 }
6798
6799 /*!
6800  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6801  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6802  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6803  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6804  * are not used here to avoid the build of big permutation array.
6805  *
6806  * \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
6807  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6808  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6809  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6810  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6811  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6812  * \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
6813  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6814  */
6815 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6816                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6817                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6818 {
6819   std::vector<const MEDCouplingUMesh *> ms2;
6820   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6821     if(*it)
6822       {
6823         (*it)->checkConnectivityFullyDefined();
6824         ms2.push_back(*it);
6825       }
6826   if(ms2.empty())
6827     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6828   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6829   int meshDim=ms2[0]->getMeshDimension();
6830   std::vector<const MEDCouplingUMesh *> m1ssm;
6831   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6832   //
6833   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6834   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6835   int fake=0,rk=0;
6836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6837   ret1->alloc(0,1); ret2->alloc(0,1);
6838   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6839     {
6840       if(meshDim!=(*it)->getMeshDimension())
6841         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6842       if(refCoo!=(*it)->getCoords())
6843         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6844       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6845       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6846       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6847       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6848         {
6849           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6850           m1ssmSingleAuto.push_back(singleCell);
6851           m1ssmSingle.push_back(singleCell);
6852           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6853         }
6854     }
6855   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6856   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6857   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6858   for(std::size_t i=0;i<m1ssm.size();i++)
6859     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6860   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6861   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6862   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6863   return ret0.retn();
6864 }
6865
6866 /*!
6867  * This method returns a newly created DataArrayInt instance.
6868  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6869  */
6870 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6871 {
6872   checkFullyDefined();
6873   const int *conn=_nodal_connec->getConstPointer();
6874   const int *connIndex=_nodal_connec_index->getConstPointer();
6875   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6876   for(const int *w=begin;w!=end;w++)
6877     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6878       ret->pushBackSilent(*w);
6879   return ret.retn();
6880 }
6881
6882 /*!
6883  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6884  * are in [0:getNumberOfCells())
6885  */
6886 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6887 {
6888   checkFullyDefined();
6889   const int *conn=_nodal_connec->getConstPointer();
6890   const int *connI=_nodal_connec_index->getConstPointer();
6891   int nbOfCells=getNumberOfCells();
6892   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6893   int *tmp=new int[nbOfCells];
6894   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6895     {
6896       int j=0;
6897       for(const int *i=connI;i!=connI+nbOfCells;i++)
6898         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6899           tmp[std::distance(connI,i)]=j++;
6900     }
6901   DataArrayInt *ret=DataArrayInt::New();
6902   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6903   ret->copyStringInfoFrom(*da);
6904   int *retPtr=ret->getPointer();
6905   const int *daPtr=da->getConstPointer();
6906   int nbOfElems=da->getNbOfElems();
6907   for(int k=0;k<nbOfElems;k++)
6908     retPtr[k]=tmp[daPtr[k]];
6909   delete [] tmp;
6910   return ret;
6911 }
6912
6913 /*!
6914  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6915  * This method \b works \b for mesh sorted by type.
6916  * cells whose ids is in 'idsPerGeoType' array.
6917  * This method conserves coords and name of mesh.
6918  */
6919 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6920 {
6921   std::vector<int> code=getDistributionOfTypes();
6922   std::size_t nOfTypesInThis=code.size()/3;
6923   int sz=0,szOfType=0;
6924   for(std::size_t i=0;i<nOfTypesInThis;i++)
6925     {
6926       if(code[3*i]!=type)
6927         sz+=code[3*i+1];
6928       else
6929         szOfType=code[3*i+1];
6930     }
6931   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6932     if(*work<0 || *work>=szOfType)
6933       {
6934         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6935         oss << ". It should be in [0," << szOfType << ") !";
6936         throw INTERP_KERNEL::Exception(oss.str().c_str());
6937       }
6938   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6939   int *idsPtr=idsTokeep->getPointer();
6940   int offset=0;
6941   for(std::size_t i=0;i<nOfTypesInThis;i++)
6942     {
6943       if(code[3*i]!=type)
6944         for(int j=0;j<code[3*i+1];j++)
6945           *idsPtr++=offset+j;
6946       else
6947         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6948       offset+=code[3*i+1];
6949     }
6950   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6951   ret->copyTinyInfoFrom(this);
6952   return ret.retn();
6953 }
6954
6955 /*!
6956  * This method returns a vector of size 'this->getNumberOfCells()'.
6957  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6958  */
6959 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6960 {
6961   int ncell=getNumberOfCells();
6962   std::vector<bool> ret(ncell);
6963   const int *cI=getNodalConnectivityIndex()->getConstPointer();
6964   const int *c=getNodalConnectivity()->getConstPointer();
6965   for(int i=0;i<ncell;i++)
6966     {
6967       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6968       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6969       ret[i]=cm.isQuadratic();
6970     }
6971   return ret;
6972 }
6973
6974 /*!
6975  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6976  */
6977 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6978 {
6979   if(other->getType()!=UNSTRUCTURED)
6980     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6981   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6982   return MergeUMeshes(this,otherC);
6983 }
6984
6985 /*!
6986  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6987  * computed by averaging coordinates of cell nodes, so this method is not a right
6988  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6989  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6990  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6991  *          components. The caller is to delete this array using decrRef() as it is
6992  *          no more needed.
6993  *  \throw If the coordinates array is not set.
6994  *  \throw If the nodal connectivity of cells is not defined.
6995  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6996  */
6997 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6998 {
6999   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7000   int spaceDim=getSpaceDimension();
7001   int nbOfCells=getNumberOfCells();
7002   ret->alloc(nbOfCells,spaceDim);
7003   ret->copyStringInfoFrom(*getCoords());
7004   double *ptToFill=ret->getPointer();
7005   const int *nodal=_nodal_connec->getConstPointer();
7006   const int *nodalI=_nodal_connec_index->getConstPointer();
7007   const double *coor=_coords->getConstPointer();
7008   for(int i=0;i<nbOfCells;i++)
7009     {
7010       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7011       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7012       ptToFill+=spaceDim;
7013     }
7014   return ret.retn();
7015 }
7016
7017 /*!
7018  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7019  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7020  * 
7021  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7022  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7023  * 
7024  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7025  * \throw If \a this is not fully defined (coordinates and connectivity)
7026  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7027  */
7028 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7029 {
7030   checkFullyDefined();
7031   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7032   int spaceDim=getSpaceDimension();
7033   int nbOfCells=getNumberOfCells();
7034   int nbOfNodes=getNumberOfNodes();
7035   ret->alloc(nbOfCells,spaceDim);
7036   double *ptToFill=ret->getPointer();
7037   const int *nodal=_nodal_connec->getConstPointer();
7038   const int *nodalI=_nodal_connec_index->getConstPointer();
7039   const double *coor=_coords->getConstPointer();
7040   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7041     {
7042       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7043       std::fill(ptToFill,ptToFill+spaceDim,0.);
7044       if(type!=INTERP_KERNEL::NORM_POLYHED)
7045         {
7046           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7047             {
7048               if(*conn>=0 && *conn<nbOfNodes)
7049                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7050               else
7051                 {
7052                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7053                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7054                 }
7055             }
7056           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7057           if(nbOfNodesInCell>0)
7058             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7059           else
7060             {
7061               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7062               throw INTERP_KERNEL::Exception(oss.str().c_str());
7063             }
7064         }
7065       else
7066         {
7067           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7068           s.erase(-1);
7069           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7070             {
7071               if(*it>=0 && *it<nbOfNodes)
7072                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7073               else
7074                 {
7075                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7076                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7077                 }
7078             }
7079           if(!s.empty())
7080             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7081           else
7082             {
7083               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7084               throw INTERP_KERNEL::Exception(oss.str().c_str());
7085             }
7086         }
7087     }
7088   return ret.retn();
7089 }
7090
7091 /*!
7092  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7093  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7094  * are specified via an array of cell ids. 
7095  *  \warning Validity of the specified cell ids is not checked! 
7096  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7097  *  \param [in] begin - an array of cell ids of interest.
7098  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7099  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7100  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7101  *          caller is to delete this array using decrRef() as it is no more needed. 
7102  *  \throw If the coordinates array is not set.
7103  *  \throw If the nodal connectivity of cells is not defined.
7104  *
7105  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7106  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7107  */
7108 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7109 {
7110   DataArrayDouble *ret=DataArrayDouble::New();
7111   int spaceDim=getSpaceDimension();
7112   int nbOfTuple=(int)std::distance(begin,end);
7113   ret->alloc(nbOfTuple,spaceDim);
7114   double *ptToFill=ret->getPointer();
7115   double *tmp=new double[spaceDim];
7116   const int *nodal=_nodal_connec->getConstPointer();
7117   const int *nodalI=_nodal_connec_index->getConstPointer();
7118   const double *coor=_coords->getConstPointer();
7119   for(const int *w=begin;w!=end;w++)
7120     {
7121       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7122       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7123       ptToFill+=spaceDim;
7124     }
7125   delete [] tmp;
7126   return ret;
7127 }
7128
7129 /*!
7130  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7131  * 
7132  */
7133 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7134 {
7135   if(!da)
7136     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7137   da->checkAllocated();
7138   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7139   ret->setCoords(da);
7140   int nbOfTuples=da->getNumberOfTuples();
7141   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7142   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7143   c->alloc(2*nbOfTuples,1);
7144   cI->alloc(nbOfTuples+1,1);
7145   int *cp=c->getPointer();
7146   int *cip=cI->getPointer();
7147   *cip++=0;
7148   for(int i=0;i<nbOfTuples;i++)
7149     {
7150       *cp++=INTERP_KERNEL::NORM_POINT1;
7151       *cp++=i;
7152       *cip++=2*(i+1);
7153     }
7154   ret->setConnectivity(c,cI,true);
7155   return ret.retn();
7156 }
7157 /*!
7158  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7159  * Cells and nodes of
7160  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7161  *  \param [in] mesh1 - the first mesh.
7162  *  \param [in] mesh2 - the second mesh.
7163  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7164  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7165  *          is no more needed.
7166  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7167  *  \throw If the coordinates array is not set in none of the meshes.
7168  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7169  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7170  */
7171 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7172 {
7173   std::vector<const MEDCouplingUMesh *> tmp(2);
7174   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7175   return MergeUMeshes(tmp);
7176 }
7177
7178 /*!
7179  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7180  * Cells and nodes of
7181  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7182  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7183  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7184  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7185  *          is no more needed.
7186  *  \throw If \a a.size() == 0.
7187  *  \throw If \a a[ *i* ] == NULL.
7188  *  \throw If the coordinates array is not set in none of the meshes.
7189  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7190  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7191 */
7192 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7193 {
7194   std::size_t sz=a.size();
7195   if(sz==0)
7196     return MergeUMeshesLL(a);
7197   for(std::size_t ii=0;ii<sz;ii++)
7198     if(!a[ii])
7199       {
7200         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7201         throw INTERP_KERNEL::Exception(oss.str().c_str());
7202       }
7203   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7204   std::vector< const MEDCouplingUMesh * > aa(sz);
7205   int spaceDim=-3;
7206   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7207     {
7208       const MEDCouplingUMesh *cur=a[i];
7209       const DataArrayDouble *coo=cur->getCoords();
7210       if(coo)
7211         spaceDim=coo->getNumberOfComponents();
7212     }
7213   if(spaceDim==-3)
7214     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7215   for(std::size_t i=0;i<sz;i++)
7216     {
7217       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7218       aa[i]=bb[i];
7219     }
7220   return MergeUMeshesLL(aa);
7221 }
7222
7223 /// @cond INTERNAL
7224
7225 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7226 {
7227   if(a.empty())
7228     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7229   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7230   int meshDim=(*it)->getMeshDimension();
7231   int nbOfCells=(*it)->getNumberOfCells();
7232   int meshLgth=(*it++)->getMeshLength();
7233   for(;it!=a.end();it++)
7234     {
7235       if(meshDim!=(*it)->getMeshDimension())
7236         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7237       nbOfCells+=(*it)->getNumberOfCells();
7238       meshLgth+=(*it)->getMeshLength();
7239     }
7240   std::vector<const MEDCouplingPointSet *> aps(a.size());
7241   std::copy(a.begin(),a.end(),aps.begin());
7242   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7243   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7244   ret->setCoords(pts);
7245   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7246   c->alloc(meshLgth,1);
7247   int *cPtr=c->getPointer();
7248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7249   cI->alloc(nbOfCells+1,1);
7250   int *cIPtr=cI->getPointer();
7251   *cIPtr++=0;
7252   int offset=0;
7253   int offset2=0;
7254   for(it=a.begin();it!=a.end();it++)
7255     {
7256       int curNbOfCell=(*it)->getNumberOfCells();
7257       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7258       const int *curC=(*it)->_nodal_connec->getConstPointer();
7259       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7260       for(int j=0;j<curNbOfCell;j++)
7261         {
7262           const int *src=curC+curCI[j];
7263           *cPtr++=*src++;
7264           for(;src!=curC+curCI[j+1];src++,cPtr++)
7265             {
7266               if(*src!=-1)
7267                 *cPtr=*src+offset2;
7268               else
7269                 *cPtr=-1;
7270             }
7271         }
7272       offset+=curCI[curNbOfCell];
7273       offset2+=(*it)->getNumberOfNodes();
7274     }
7275   //
7276   ret->setConnectivity(c,cI,true);
7277   return ret.retn();
7278 }
7279
7280 /// @endcond
7281
7282 /*!
7283  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7284  * dimension and sharing the node coordinates array.
7285  * All cells of the first mesh precede all cells of the second mesh
7286  * within the result mesh. 
7287  *  \param [in] mesh1 - the first mesh.
7288  *  \param [in] mesh2 - the second mesh.
7289  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7290  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7291  *          is no more needed.
7292  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7293  *  \throw If the meshes do not share the node coordinates array.
7294  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7295  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7296  */
7297 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7298 {
7299   std::vector<const MEDCouplingUMesh *> tmp(2);
7300   tmp[0]=mesh1; tmp[1]=mesh2;
7301   return MergeUMeshesOnSameCoords(tmp);
7302 }
7303
7304 /*!
7305  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7306  * dimension and sharing the node coordinates array.
7307  * All cells of the *i*-th mesh precede all cells of the
7308  * (*i*+1)-th mesh within the result mesh.
7309  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7310  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7311  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7312  *          is no more needed.
7313  *  \throw If \a a.size() == 0.
7314  *  \throw If \a a[ *i* ] == NULL.
7315  *  \throw If the meshes do not share the node coordinates array.
7316  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7317  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7318  */
7319 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7320 {
7321   if(meshes.empty())
7322     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7323   for(std::size_t ii=0;ii<meshes.size();ii++)
7324     if(!meshes[ii])
7325       {
7326         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7327         throw INTERP_KERNEL::Exception(oss.str().c_str());
7328       }
7329   const DataArrayDouble *coords=meshes.front()->getCoords();
7330   int meshDim=meshes.front()->getMeshDimension();
7331   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7332   int meshLgth=0;
7333   int meshIndexLgth=0;
7334   for(;iter!=meshes.end();iter++)
7335     {
7336       if(coords!=(*iter)->getCoords())
7337         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7338       if(meshDim!=(*iter)->getMeshDimension())
7339         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7340       meshLgth+=(*iter)->getMeshLength();
7341       meshIndexLgth+=(*iter)->getNumberOfCells();
7342     }
7343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7344   nodal->alloc(meshLgth,1);
7345   int *nodalPtr=nodal->getPointer();
7346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7347   nodalIndex->alloc(meshIndexLgth+1,1);
7348   int *nodalIndexPtr=nodalIndex->getPointer();
7349   int offset=0;
7350   for(iter=meshes.begin();iter!=meshes.end();iter++)
7351     {
7352       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7353       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7354       int nbOfCells=(*iter)->getNumberOfCells();
7355       int meshLgth2=(*iter)->getMeshLength();
7356       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7357       if(iter!=meshes.begin())
7358         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7359       else
7360         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7361       offset+=meshLgth2;
7362     }
7363   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7364   ret->setName("merge");
7365   ret->setMeshDimension(meshDim);
7366   ret->setConnectivity(nodal,nodalIndex,true);
7367   ret->setCoords(coords);
7368   return ret;
7369 }
7370
7371 /*!
7372  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7373  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7374  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7375  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7376  * New" mode are returned for each input mesh.
7377  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7378  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7379  *          valid values [0,1,2], see zipConnectivityTraducer().
7380  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7381  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7382  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7383  *          no more needed.
7384  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7385  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7386  *          is no more needed.
7387  *  \throw If \a meshes.size() == 0.
7388  *  \throw If \a meshes[ *i* ] == NULL.
7389  *  \throw If the meshes do not share the node coordinates array.
7390  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7391  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7392  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7393  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7394  */
7395 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7396 {
7397   //All checks are delegated to MergeUMeshesOnSameCoords
7398   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7400   corr.resize(meshes.size());
7401   std::size_t nbOfMeshes=meshes.size();
7402   int offset=0;
7403   const int *o2nPtr=o2n->getConstPointer();
7404   for(std::size_t i=0;i<nbOfMeshes;i++)
7405     {
7406       DataArrayInt *tmp=DataArrayInt::New();
7407       int curNbOfCells=meshes[i]->getNumberOfCells();
7408       tmp->alloc(curNbOfCells,1);
7409       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7410       offset+=curNbOfCells;
7411       tmp->setName(meshes[i]->getName());
7412       corr[i]=tmp;
7413     }
7414   return ret.retn();
7415 }
7416
7417 /*!
7418  * Makes all given meshes share the nodal connectivity array. The common connectivity
7419  * array is created by concatenating the connectivity arrays of all given meshes. All
7420  * the given meshes must be of the same space dimension but dimension of cells **can
7421  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7422  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7423  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7424  *  \param [in,out] meshes - a vector of meshes to update.
7425  *  \throw If any of \a meshes is NULL.
7426  *  \throw If the coordinates array is not set in any of \a meshes.
7427  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7428  *  \throw If \a meshes are of different space dimension.
7429  */
7430 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7431 {
7432   std::size_t sz=meshes.size();
7433   if(sz==0 || sz==1)
7434     return;
7435   std::vector< const DataArrayDouble * > coords(meshes.size());
7436   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7437   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7438     {
7439       if((*it))
7440         {
7441           (*it)->checkConnectivityFullyDefined();
7442           const DataArrayDouble *coo=(*it)->getCoords();
7443           if(coo)
7444             *it2=coo;
7445           else
7446             {
7447               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7448               oss << " has no coordinate array defined !";
7449               throw INTERP_KERNEL::Exception(oss.str().c_str());
7450             }
7451         }
7452       else
7453         {
7454           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7455           oss << " is null !";
7456           throw INTERP_KERNEL::Exception(oss.str().c_str());
7457         }
7458     }
7459   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7460   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7461   int offset=(*it)->getNumberOfNodes();
7462   (*it++)->setCoords(res);
7463   for(;it!=meshes.end();it++)
7464     {
7465       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7466       (*it)->setCoords(res);
7467       (*it)->shiftNodeNumbersInConn(offset);
7468       offset+=oldNumberOfNodes;
7469     }
7470 }
7471
7472 /*!
7473  * Merges nodes coincident with a given precision within all given meshes that share
7474  * the nodal connectivity array. The given meshes **can be of different** mesh
7475  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7476  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7477  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7478  *  \param [in,out] meshes - a vector of meshes to update.
7479  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7480  *  \throw If any of \a meshes is NULL.
7481  *  \throw If the \a meshes do not share the same node coordinates array.
7482  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7483  */
7484 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7485 {
7486   if(meshes.empty())
7487     return ;
7488   std::set<const DataArrayDouble *> s;
7489   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7490     {
7491       if(*it)
7492         s.insert((*it)->getCoords());
7493       else
7494         {
7495           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 !";
7496           throw INTERP_KERNEL::Exception(oss.str().c_str());
7497         }
7498     }
7499   if(s.size()!=1)
7500     {
7501       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 !";
7502       throw INTERP_KERNEL::Exception(oss.str().c_str());
7503     }
7504   const DataArrayDouble *coo=*(s.begin());
7505   if(!coo)
7506     return;
7507   //
7508   DataArrayInt *comm,*commI;
7509   coo->findCommonTuples(eps,-1,comm,commI);
7510   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7511   int oldNbOfNodes=coo->getNumberOfTuples();
7512   int newNbOfNodes;
7513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7514   if(oldNbOfNodes==newNbOfNodes)
7515     return ;
7516   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7517   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7518     {
7519       (*it)->renumberNodesInConn(o2n->getConstPointer());
7520       (*it)->setCoords(newCoords);
7521     } 
7522 }
7523
7524 /*!
7525  * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [ \a connBg , \a connEnd ) and returns its extruded cell by inserting the result at the end of ret.
7526  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7527  * \param isQuad specifies the policy of connectivity.
7528  * @ret in/out parameter in which the result will be append
7529  */
7530 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7531 {
7532   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7533   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7534   ret.push_back(cm.getExtrudedType());
7535   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7536   switch(flatType)
7537     {
7538     case INTERP_KERNEL::NORM_POINT1:
7539       {
7540         ret.push_back(connBg[1]);
7541         ret.push_back(connBg[1]+nbOfNodesPerLev);
7542         break;
7543       }
7544     case INTERP_KERNEL::NORM_SEG2:
7545       {
7546         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7547         ret.insert(ret.end(),conn,conn+4);
7548         break;
7549       }
7550     case INTERP_KERNEL::NORM_SEG3:
7551       {
7552         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7553         ret.insert(ret.end(),conn,conn+8);
7554         break;
7555       }
7556     case INTERP_KERNEL::NORM_QUAD4:
7557       {
7558         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7559         ret.insert(ret.end(),conn,conn+8);
7560         break;
7561       }
7562     case INTERP_KERNEL::NORM_TRI3:
7563       {
7564         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7565         ret.insert(ret.end(),conn,conn+6);
7566         break;
7567       }
7568     case INTERP_KERNEL::NORM_TRI6:
7569       {
7570         int conn[15]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4],connBg[5],connBg[6],connBg[4]+deltaz,connBg[5]+deltaz,connBg[6]+deltaz,
7571                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7572         ret.insert(ret.end(),conn,conn+15);
7573         break;
7574       }
7575     case INTERP_KERNEL::NORM_QUAD8:
7576       {
7577         int conn[20]={
7578           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7579           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7580           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7581         };
7582         ret.insert(ret.end(),conn,conn+20);
7583         break;
7584       }
7585     case INTERP_KERNEL::NORM_POLYGON:
7586       {
7587         std::back_insert_iterator< std::vector<int> > ii(ret);
7588         std::copy(connBg+1,connEnd,ii);
7589         *ii++=-1;
7590         std::reverse_iterator<const int *> rConnBg(connEnd);
7591         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7592         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7593         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7594         for(std::size_t i=0;i<nbOfRadFaces;i++)
7595           {
7596             *ii++=-1;
7597             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7598             std::copy(conn,conn+4,ii);
7599           }
7600         break;
7601       }
7602     default:
7603       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7604     }
7605 }
7606
7607 /*!
7608  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7609  */
7610 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7611 {
7612   double v[3]={0.,0.,0.};
7613   std::size_t sz=std::distance(begin,end);
7614   if(isQuadratic)
7615     sz/=2;
7616   for(std::size_t i=0;i<sz;i++)
7617     {
7618       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];
7619       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7620       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7621     }
7622   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7623 }
7624
7625 /*!
7626  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7627  */
7628 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7629 {
7630   std::vector<std::pair<int,int> > edges;
7631   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7632   const int *bgFace=begin;
7633   for(std::size_t i=0;i<nbOfFaces;i++)
7634     {
7635       const int *endFace=std::find(bgFace+1,end,-1);
7636       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7637       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7638         {
7639           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7640           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7641             return false;
7642           edges.push_back(p1);
7643         }
7644       bgFace=endFace+1;
7645     }
7646   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7647 }
7648
7649 /*!
7650  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7651  */
7652 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7653 {
7654   double vec0[3],vec1[3];
7655   std::size_t sz=std::distance(begin,end);
7656   if(sz%2!=0)
7657     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7658   int nbOfNodes=(int)sz/2;
7659   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7660   const double *pt0=coords+3*begin[0];
7661   const double *pt1=coords+3*begin[nbOfNodes];
7662   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7663   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7664 }
7665
7666 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7667 {
7668   std::size_t sz=std::distance(begin,end);
7669   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7670   std::size_t nbOfNodes(sz/2);
7671   std::copy(begin,end,(int *)tmp);
7672   for(std::size_t j=1;j<nbOfNodes;j++)
7673     {
7674       begin[j]=tmp[nbOfNodes-j];
7675       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7676     }
7677 }
7678
7679 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7680 {
7681   std::size_t sz=std::distance(begin,end);
7682   if(sz!=4)
7683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7684   double vec0[3],vec1[3];
7685   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7686   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]; 
7687   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;
7688 }
7689
7690 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7691 {
7692   std::size_t sz=std::distance(begin,end);
7693   if(sz!=5)
7694     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7695   double vec0[3];
7696   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7697   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7698   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7699 }
7700
7701 /*!
7702  * 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 ) 
7703  * 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
7704  * a 2D space.
7705  *
7706  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7707  * \param [in] coords the coordinates with nb of components exactly equal to 3
7708  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7709  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7710  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7711  */
7712 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7713 {
7714   int nbFaces=std::count(begin+1,end,-1)+1;
7715   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7716   double *vPtr=v->getPointer();
7717   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7718   double *pPtr=p->getPointer();
7719   const int *stFaceConn=begin+1;
7720   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7721     {
7722       const int *endFaceConn=std::find(stFaceConn,end,-1);
7723       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7724       stFaceConn=endFaceConn+1;
7725     }
7726   pPtr=p->getPointer(); vPtr=v->getPointer();
7727   DataArrayInt *comm1=0,*commI1=0;
7728   v->findCommonTuples(eps,-1,comm1,commI1);
7729   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7730   const int *comm1Ptr=comm1->getConstPointer();
7731   const int *commI1Ptr=commI1->getConstPointer();
7732   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7733   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7734   //
7735   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7736   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7737   mm->finishInsertingCells();
7738   //
7739   for(int i=0;i<nbOfGrps1;i++)
7740     {
7741       int vecId=comm1Ptr[commI1Ptr[i]];
7742       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7743       DataArrayInt *comm2=0,*commI2=0;
7744       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7745       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7746       const int *comm2Ptr=comm2->getConstPointer();
7747       const int *commI2Ptr=commI2->getConstPointer();
7748       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7749       for(int j=0;j<nbOfGrps2;j++)
7750         {
7751           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7752             {
7753               res->insertAtTheEnd(begin,end);
7754               res->pushBackSilent(-1);
7755             }
7756           else
7757             {
7758               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7759               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7760               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7761               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7762               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7763               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7764               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7765               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7766               const int *idsNodePtr=idsNode->getConstPointer();
7767               double center[3]; center[0]=pPtr[pointId]*vPtr[3*vecId]; center[1]=pPtr[pointId]*vPtr[3*vecId+1]; center[2]=pPtr[pointId]*vPtr[3*vecId+2];
7768               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7769               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7770               if(std::abs(norm)>eps)
7771                 {
7772                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7773                   mm3->rotate(center,vec,angle);
7774                 }
7775               mm3->changeSpaceDimension(2);
7776               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7777               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7778               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7779               int nbOfCells=mm4->getNumberOfCells();
7780               for(int k=0;k<nbOfCells;k++)
7781                 {
7782                   int l=0;
7783                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7784                     res->pushBackSilent(idsNodePtr[*work]);
7785                   res->pushBackSilent(-1);
7786                 }
7787             }
7788         }
7789     }
7790   res->popBackSilent();
7791 }
7792
7793 /*!
7794  * 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
7795  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7796  * 
7797  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7798  * \param [in] coords coordinates expected to have 3 components.
7799  * \param [in] begin start of the nodal connectivity of the face.
7800  * \param [in] end end of the nodal connectivity (excluded) of the face.
7801  * \param [out] v the normalized vector of size 3
7802  * \param [out] p the pos of plane
7803  */
7804 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7805 {
7806   std::size_t nbPoints=std::distance(begin,end);
7807   if(nbPoints<3)
7808     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7809   double vec[3]={0.,0.,0.};
7810   std::size_t j=0;
7811   bool refFound=false;
7812   for(;j<nbPoints-1 && !refFound;j++)
7813     {
7814       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7815       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7816       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7817       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7818       if(norm>eps)
7819         {
7820           refFound=true;
7821           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7822         }
7823     }
7824   for(std::size_t i=j;i<nbPoints-1;i++)
7825     {
7826       double curVec[3];
7827       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7828       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7829       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7830       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7831       if(norm<eps)
7832         continue;
7833       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7834       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];
7835       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7836       if(norm>eps)
7837         {
7838           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7839           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7840           return ;
7841         }
7842     }
7843   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7844 }
7845
7846 /*!
7847  * This method tries to obtain a well oriented polyhedron.
7848  * If the algorithm fails, an exception will be thrown.
7849  */
7850 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7851 {
7852   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7853   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7854   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7855   isPerm[0]=true;
7856   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7857   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7858   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7859   //
7860   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7861     {
7862       bgFace=begin;
7863       std::size_t smthChanged=0;
7864       for(std::size_t i=0;i<nbOfFaces;i++)
7865         {
7866           endFace=std::find(bgFace+1,end,-1);
7867           nbOfEdgesInFace=std::distance(bgFace,endFace);
7868           if(!isPerm[i])
7869             {
7870               bool b;
7871               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7872                 {
7873                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7874                   std::pair<int,int> p2(p1.second,p1.first);
7875                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7876                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7877                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7878                 }
7879               if(isPerm[i])
7880                 { 
7881                   if(!b)
7882                     std::reverse(bgFace+1,endFace);
7883                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7884                     {
7885                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7886                       std::pair<int,int> p2(p1.second,p1.first);
7887                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7888                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7889                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7890                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7891                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7892                       if(it!=edgesOK.end())
7893                         {
7894                           edgesOK.erase(it);
7895                           edgesFinished.push_back(p1);
7896                         }
7897                       else
7898                         edgesOK.push_back(p1);
7899                     }
7900                 }
7901             }
7902           bgFace=endFace+1;
7903         }
7904       if(smthChanged==0)
7905         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7906     }
7907   if(!edgesOK.empty())
7908     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7909   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7910     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7911       bgFace=begin;
7912       for(std::size_t i=0;i<nbOfFaces;i++)
7913         {
7914           endFace=std::find(bgFace+1,end,-1);
7915           std::reverse(bgFace+1,endFace);
7916           bgFace=endFace+1;
7917         }
7918     }
7919 }
7920
7921 /*!
7922  * This method makes the assumption spacedimension == meshdimension == 2.
7923  * This method works only for linear cells.
7924  * 
7925  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7926  */
7927 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7928 {
7929   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7930     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7931   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7932   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7933   int nbOfNodesExpected=m->getNumberOfNodes();
7934   if(m->getNumberOfCells()!=nbOfNodesExpected)
7935     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7936   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7937   const int *n2oPtr=n2o->getConstPointer();
7938   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7939   m->getReverseNodalConnectivity(revNodal,revNodalI);
7940   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7941   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7942   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7943   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7944   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7945   if(nbOfNodesExpected<1)
7946     return ret.retn();
7947   int prevCell=0;
7948   int prevNode=nodalPtr[nodalIPtr[0]+1];
7949   *work++=n2oPtr[prevNode];
7950   for(int i=1;i<nbOfNodesExpected;i++)
7951     {
7952       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7953         {
7954           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7955           conn.erase(prevNode);
7956           if(conn.size()==1)
7957             {
7958               int curNode=*(conn.begin());
7959               *work++=n2oPtr[curNode];
7960               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7961               shar.erase(prevCell);
7962               if(shar.size()==1)
7963                 {
7964                   prevCell=*(shar.begin());
7965                   prevNode=curNode;
7966                 }
7967               else
7968                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7969             }
7970           else
7971             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7972         }
7973       else
7974         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7975     }
7976   return ret.retn();
7977 }
7978
7979 /*!
7980  * This method makes the assumption spacedimension == meshdimension == 3.
7981  * This method works only for linear cells.
7982  * 
7983  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7984  */
7985 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7986 {
7987   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7988     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7989   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7990   const int *conn=m->getNodalConnectivity()->getConstPointer();
7991   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7992   int nbOfCells=m->getNumberOfCells();
7993   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7994   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7995   if(nbOfCells<1)
7996     return ret.retn();
7997   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7998   for(int i=1;i<nbOfCells;i++)
7999     {
8000       *work++=-1;
8001       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8002     }
8003   return ret.retn();
8004 }
8005
8006 /*!
8007  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8008  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8009  */
8010 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8011 {
8012   double *w=zipFrmt;
8013   if(spaceDim==3)
8014     for(int i=0;i<nbOfNodesInCell;i++)
8015       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8016   else if(spaceDim==2)
8017     {
8018       for(int i=0;i<nbOfNodesInCell;i++)
8019         {
8020           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8021           *w++=0.;
8022         }
8023     }
8024   else
8025     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8026 }
8027
8028 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8029 {
8030   int nbOfCells=getNumberOfCells();
8031   if(nbOfCells<=0)
8032     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8033   static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,-1,4};
8034   ofs << "  <" << getVTKDataSetType() << ">\n";
8035   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8036   ofs << "      <PointData>\n" << pointData << std::endl;
8037   ofs << "      </PointData>\n";
8038   ofs << "      <CellData>\n" << cellData << std::endl;
8039   ofs << "      </CellData>\n";
8040   ofs << "      <Points>\n";
8041   if(getSpaceDimension()==3)
8042     _coords->writeVTK(ofs,8,"Points");
8043   else
8044     {
8045       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8046       coo->writeVTK(ofs,8,"Points");
8047     }
8048   ofs << "      </Points>\n";
8049   ofs << "      <Cells>\n";
8050   const int *cPtr=_nodal_connec->getConstPointer();
8051   const int *cIPtr=_nodal_connec_index->getConstPointer();
8052   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8053   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8054   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8055   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8056   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8057   int szFaceOffsets=0,szConn=0;
8058   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8059     {
8060       *w2=cPtr[cIPtr[i]];
8061       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8062         {
8063           *w1=-1;
8064           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8065           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8066         }
8067       else
8068         {
8069           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8070           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8071           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8072           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8073           w4=std::copy(c.begin(),c.end(),w4);
8074         }
8075     }
8076   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8077   types->writeVTK(ofs,8,"UInt8","types");
8078   offsets->writeVTK(ofs,8,"Int32","offsets");
8079   if(szFaceOffsets!=0)
8080     {//presence of Polyhedra
8081       connectivity->reAlloc(szConn);
8082       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8083       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8084       w1=faces->getPointer();
8085       for(int i=0;i<nbOfCells;i++)
8086         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8087           {
8088             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8089             *w1++=nbFaces;
8090             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8091             for(int j=0;j<nbFaces;j++)
8092               {
8093                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8094                 *w1++=(int)std::distance(w6,w5);
8095                 w1=std::copy(w6,w5,w1);
8096                 w6=w5+1;
8097               }
8098           }
8099       faces->writeVTK(ofs,8,"Int32","faces");
8100     }
8101   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8102   ofs << "      </Cells>\n";
8103   ofs << "    </Piece>\n";
8104   ofs << "  </" << getVTKDataSetType() << ">\n";
8105 }
8106
8107 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8108 {
8109   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8110   if(_mesh_dim==-2)
8111     { stream << " Not set !"; return ; }
8112   stream << " Mesh dimension : " << _mesh_dim << ".";
8113   if(_mesh_dim==-1)
8114     return ;
8115   if(!_coords)
8116     { stream << " No coordinates set !"; return ; }
8117   if(!_coords->isAllocated())
8118     { stream << " Coordinates set but not allocated !"; return ; }
8119   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8120   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8121   if(!_nodal_connec_index)
8122     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8123   if(!_nodal_connec_index->isAllocated())
8124     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8125   int lgth=_nodal_connec_index->getNumberOfTuples();
8126   int cpt=_nodal_connec_index->getNumberOfComponents();
8127   if(cpt!=1 || lgth<1)
8128     return ;
8129   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8130 }
8131
8132 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8133 {
8134   return std::string("UnstructuredGrid");
8135 }
8136
8137 /*!
8138  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8139  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8140  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8141  * meshes.
8142  *  \param [in] m1 - the first input mesh which is a partitioned object.
8143  *  \param [in] m2 - the second input mesh which is a partition tool.
8144  *  \param [in] eps - precision used to detect coincident mesh entities.
8145  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8146  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8147  *         this array using decrRef() as it is no more needed.
8148  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8149  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8150  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8151  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8152  *         it is no more needed.  
8153  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8154  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8155  *         is no more needed.  
8156  *  \throw If the coordinates array is not set in any of the meshes.
8157  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8158  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8159  */
8160 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8161 {
8162   m1->checkFullyDefined();
8163   m2->checkFullyDefined();
8164   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8165     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8166   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8167   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8168   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8169   std::vector<double> addCoo,addCoordsQuadratic;
8170   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8171   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8172   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8173                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8174   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8176   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8177   std::vector< std::vector<int> > intersectEdge2;
8178   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8179   subDiv2.clear(); dd5=0; dd6=0;
8180   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8181   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8182   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8183                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8184   //
8185   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8186   addCooDa->alloc((int)(addCoo.size())/2,2);
8187   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8188   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8189   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8190   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8191   std::vector<const DataArrayDouble *> coordss(4);
8192   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8193   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8194   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8195   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8196   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8197   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8198   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8199   ret->setConnectivity(conn,connI,true);
8200   ret->setCoords(coo);
8201   cellNb1=c1.retn(); cellNb2=c2.retn();
8202   return ret.retn();
8203 }
8204
8205 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8206                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8207                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8208                                                          const std::vector<double>& addCoords,
8209                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8210 {
8211   static const int SPACEDIM=2;
8212   std::vector<double> bbox1,bbox2;
8213   const double *coo1=m1->getCoords()->getConstPointer();
8214   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8215   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8216   int offset1=m1->getNumberOfNodes();
8217   const double *coo2=m2->getCoords()->getConstPointer();
8218   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8219   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8220   int offset2=offset1+m2->getNumberOfNodes();
8221   int offset3=offset2+((int)addCoords.size())/2;
8222   m1->getBoundingBoxForBBTree(bbox1);
8223   m2->getBoundingBoxForBBTree(bbox2);
8224   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8225   int ncell1=m1->getNumberOfCells();
8226   crI.push_back(0);
8227   for(int i=0;i<ncell1;i++)
8228     {
8229       std::vector<int> candidates2;
8230       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8231       std::map<INTERP_KERNEL::Node *,int> mapp;
8232       std::map<int,INTERP_KERNEL::Node *> mappRev;
8233       INTERP_KERNEL::QuadraticPolygon pol1;
8234       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8235       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8236       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8237       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8238                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8239       //
8240       std::set<INTERP_KERNEL::Edge *> edges1;// store all edges of pol1 that are NOT consumed by intersect cells. If any after iteration over candidates2 -> a part of pol1 should appear in result
8241       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8242       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8243       for(it1.first();!it1.finished();it1.next())
8244         edges1.insert(it1.current()->getPtr());
8245       //
8246       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8247       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8248       int ii=0;
8249       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8250         {
8251           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8252           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8253           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8254           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8255                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8256         }
8257       ii=0;
8258       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8259         {
8260           pol1.initLocationsWithOther(pol2s[ii]);
8261           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8262           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8263           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8264         }
8265       if(!edges1.empty())
8266         {
8267           try
8268             {
8269               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8270             }
8271           catch(INTERP_KERNEL::Exception& e)
8272             {
8273               std::ostringstream oss; oss << "Error when computing residual of cell #" << i << " in source/m1 mesh ! Maybe the neighbours of this cell in mesh are not well connected !\n" << "The deep reason is the following : " << e.what();
8274               throw INTERP_KERNEL::Exception(oss.str().c_str());
8275             }
8276         }
8277       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8278         (*it).second->decrRef();
8279     }
8280 }
8281
8282 /*!
8283  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8284  * 
8285  */
8286 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8287                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8288                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8289                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8290                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8291 {
8292   static const int SPACEDIM=2;
8293   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8294   desc2=DataArrayInt::New();
8295   descIndx2=DataArrayInt::New();
8296   revDesc2=DataArrayInt::New();
8297   revDescIndx2=DataArrayInt::New();
8298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8300   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8301   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8302   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8303   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8304   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8305   std::vector<double> bbox1,bbox2;
8306   m1Desc->getBoundingBoxForBBTree(bbox1);
8307   m2Desc->getBoundingBoxForBBTree(bbox2);
8308   int ncell1=m1Desc->getNumberOfCells();
8309   int ncell2=m2Desc->getNumberOfCells();
8310   intersectEdge1.resize(ncell1);
8311   colinear2.resize(ncell2);
8312   subDiv2.resize(ncell2);
8313   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8314   std::vector<int> candidates1(1);
8315   int offset1=m1->getNumberOfNodes();
8316   int offset2=offset1+m2->getNumberOfNodes();
8317   for(int i=0;i<ncell1;i++)
8318     {
8319       std::vector<int> candidates2;
8320       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8321       if(!candidates2.empty())
8322         {
8323           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8324           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8325           candidates1[0]=i;
8326           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8327           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8328           delete pol2;
8329           delete pol1;
8330         }
8331       else
8332         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8333     }
8334   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8335   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8336 }
8337
8338 /*!
8339  * This method performs the 2nd step of Partition of 2D mesh.
8340  * This method has 4 inputs :
8341  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8342  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8343  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8344  * The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
8345  * \param m1 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
8346  * \param m2 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method.
8347  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8348  */
8349 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge) throw(INTERP_KERNEL::Exception)
8350 {
8351   int offset1=m1->getNumberOfNodes();
8352   int ncell=m2->getNumberOfCells();
8353   const int *c=m2->getNodalConnectivity()->getConstPointer();
8354   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8355   const double *coo=m2->getCoords()->getConstPointer();
8356   const double *cooBis=m1->getCoords()->getConstPointer();
8357   int offset2=offset1+m2->getNumberOfNodes();
8358   intersectEdge.resize(ncell);
8359   for(int i=0;i<ncell;i++,cI++)
8360     {
8361       const std::vector<int>& divs=subDiv[i];
8362       int nnode=cI[1]-cI[0]-1;
8363       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8364       std::map<INTERP_KERNEL::Node *, int> mapp22;
8365       for(int j=0;j<nnode;j++)
8366         {
8367           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8368           int nnid=c[(*cI)+j+1];
8369           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8370           mapp22[nn]=nnid+offset1;
8371         }
8372       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8373       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8374         ((*it).second.first)->decrRef();
8375       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8376       std::map<INTERP_KERNEL::Node *,int> mapp3;
8377       for(std::size_t j=0;j<divs.size();j++)
8378         {
8379           int id=divs[j];
8380           INTERP_KERNEL::Node *tmp=0;
8381           if(id<offset1)
8382             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8383           else if(id<offset2)
8384             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8385           else
8386             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8387           addNodes[j]=tmp;
8388           mapp3[tmp]=id;
8389         }
8390       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8391       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8392         (*it)->decrRef();
8393       e->decrRef();
8394     }
8395 }
8396
8397 /*!
8398  * This method is part of the Slice3D algorithm. It is the first step of assembly process, ones coordinates have been computed (by MEDCouplingUMesh::split3DCurveWithPlane method).
8399  * This method allows to compute given the status of 3D curve cells and the descending connectivity 3DSurf->3DCurve to deduce the intersection of each 3D surf cells
8400  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8401  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8402  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8403  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8404  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8405  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8406  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8407  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8408  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8409  * \param [out] cut3DSuf input/output param.
8410  */
8411 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8412                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8413                                                    const int *desc, const int *descIndx, 
8414                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8415 {
8416   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8417   int nbOf3DSurfCell=(int)cut3DSurf.size();
8418   for(int i=0;i<nbOf3DSurfCell;i++)
8419     {
8420       std::vector<int> res;
8421       int offset=descIndx[i];
8422       int nbOfSeg=descIndx[i+1]-offset;
8423       for(int j=0;j<nbOfSeg;j++)
8424         {
8425           int edgeId=desc[offset+j];
8426           int status=cut3DCurve[edgeId];
8427           if(status!=-2)
8428             {
8429               if(status>-1)
8430                 res.push_back(status);
8431               else
8432                 {
8433                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8434                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8435                 }
8436             }
8437         }
8438       switch(res.size())
8439         {
8440         case 2:
8441           {
8442             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8443             break;
8444           }
8445         case 1:
8446         case 0:
8447           {
8448             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8449             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8450             if(res.size()==2)
8451               {
8452                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8453               }
8454             else
8455               {
8456                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8457               }
8458             break;
8459           }
8460         default:
8461           {// case when plane is on a multi colinear edge of a polyhedron
8462             if((int)res.size()==2*nbOfSeg)
8463               {
8464                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8465               }
8466             else
8467               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8468           }
8469         }
8470     }
8471 }
8472
8473 /*!
8474  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8475  * This method is part of the Slice3D algorithm. It is the second step of assembly process, ones coordinates have been computed (by MEDCouplingUMesh::split3DCurveWithPlane method).
8476  * This method allows to compute given the result of 3D surf cells with plane and the descending connectivity 3D->3DSurf to deduce the intersection of each 3D cells
8477  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8478  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8479  * \param desc is the descending connectivity 3D->3DSurf
8480  * \param descIndx is the descending connectivity index 3D->3DSurf
8481  */
8482 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8483                                                   const int *desc, const int *descIndx,
8484                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8485 {
8486   checkFullyDefined();
8487   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8488     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8489   const int *nodal3D=_nodal_connec->getConstPointer();
8490   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8491   int nbOfCells=getNumberOfCells();
8492   for(int i=0;i<nbOfCells;i++)
8493     {
8494       std::map<int, std::set<int> > m;
8495       int offset=descIndx[i];
8496       int nbOfFaces=descIndx[i+1]-offset;
8497       int start=-1;
8498       int end=-1;
8499       for(int j=0;j<nbOfFaces;j++)
8500         {
8501           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8502           if(p.first!=-1 && p.second!=-1)
8503             {
8504               if(p.first!=-2)
8505                 {
8506                   start=p.first; end=p.second;
8507                   m[p.first].insert(p.second);
8508                   m[p.second].insert(p.first);
8509                 }
8510               else
8511                 {
8512                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8513                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8514                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8515                   INTERP_KERNEL::NormalizedCellType cmsId;
8516                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8517                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8518                   for(unsigned k=0;k<nbOfNodesSon;k++)
8519                     {
8520                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8521                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8522                     }
8523                 }
8524             }
8525         }
8526       if(m.empty())
8527         continue;
8528       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8529       int prev=end;
8530       while(end!=start)
8531         {
8532           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8533           const std::set<int>& s=(*it).second;
8534           std::set<int> s2; s2.insert(prev);
8535           std::set<int> s3;
8536           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8537           if(s3.size()==1)
8538             {
8539               int val=*s3.begin();
8540               conn.push_back(start);
8541               prev=start;
8542               start=val;
8543             }
8544           else
8545             start=end;
8546         }
8547       conn.push_back(end);
8548       if(conn.size()>3)
8549         {
8550           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8551           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8552           cellIds->pushBackSilent(i);
8553         }
8554     }
8555 }
8556
8557 /*!
8558  * 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
8559  * 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
8560  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8561  * 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
8562  * 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.
8563  * 
8564  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8565  */
8566 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8567 {
8568   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8569   if(sz>=4)
8570     {
8571       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8572       if(cm.getDimension()==2)
8573         {
8574           const int *node=nodalConnBg+1;
8575           int startNode=*node++;
8576           double refX=coords[2*startNode];
8577           for(;node!=nodalConnEnd;node++)
8578             {
8579               if(coords[2*(*node)]<refX)
8580                 {
8581                   startNode=*node;
8582                   refX=coords[2*startNode];
8583                 }
8584             }
8585           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8586           refX=1e300;
8587           double tmp1;
8588           double tmp2[2];
8589           double angle0=-M_PI/2;
8590           //
8591           int nextNode=-1;
8592           int prevNode=-1;
8593           double resRef;
8594           double angleNext=0.;
8595           while(nextNode!=startNode)
8596             {
8597               nextNode=-1;
8598               resRef=1e300;
8599               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8600                 {
8601                   if(*node!=tmpOut.back() && *node!=prevNode)
8602                     {
8603                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8604                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8605                       double res;
8606                       if(angleM<=angle0)
8607                         res=angle0-angleM;
8608                       else
8609                         res=angle0-angleM+2.*M_PI;
8610                       if(res<resRef)
8611                         {
8612                           nextNode=*node;
8613                           resRef=res;
8614                           angleNext=angleM;
8615                         }
8616                     }
8617                 }
8618               if(nextNode!=startNode)
8619                 {
8620                   angle0=angleNext-M_PI;
8621                   if(angle0<-M_PI)
8622                     angle0+=2*M_PI;
8623                   prevNode=tmpOut.back();
8624                   tmpOut.push_back(nextNode);
8625                 }
8626             }
8627           std::vector<int> tmp3(2*(sz-1));
8628           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8629           std::copy(nodalConnBg+1,nodalConnEnd,it);
8630           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8631             {
8632               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8633               return false;
8634             }
8635           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8636             {
8637               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8638               return false;
8639             }
8640           else
8641             {
8642               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8643               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8644               return true;
8645             }
8646         }
8647       else
8648         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8649     }
8650   else
8651     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8652 }
8653
8654 /*!
8655  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8656  * 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.
8657  * 
8658  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8659  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8660  * \param [in,out] arr array in which the remove operation will be done.
8661  * \param [in,out] arrIndx array in the remove operation will modify
8662  * \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])
8663  * \return true if \b arr and \b arrIndx have been modified, false if not.
8664  */
8665 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8666 {
8667   if(!arrIndx || !arr)
8668     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8669   if(offsetForRemoval<0)
8670     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8671   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8672   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8673   int *arrIPtr=arrIndx->getPointer();
8674   *arrIPtr++=0;
8675   int previousArrI=0;
8676   const int *arrPtr=arr->getConstPointer();
8677   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8678   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8679     {
8680       if(*arrIPtr-previousArrI>offsetForRemoval)
8681         {
8682           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8683             {
8684               if(s.find(*work)==s.end())
8685                 arrOut.push_back(*work);
8686             }
8687         }
8688       previousArrI=*arrIPtr;
8689       *arrIPtr=(int)arrOut.size();
8690     }
8691   if(arr->getNumberOfTuples()==(int)arrOut.size())
8692     return false;
8693   arr->alloc((int)arrOut.size(),1);
8694   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8695   return true;
8696 }
8697
8698 /*!
8699  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8700  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8701  * The selection of extraction is done standardly in new2old format.
8702  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8703  *
8704  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8705  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8706  * \param [in] arrIn arr origin array from which the extraction will be done.
8707  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8708  * \param [out] arrOut the resulting array
8709  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8710  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8711  */
8712 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8713                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8714 {
8715   if(!arrIn || !arrIndxIn)
8716     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8717   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8718   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8720   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8721   const int *arrInPtr=arrIn->getConstPointer();
8722   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8723   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8724   if(nbOfGrps<0)
8725     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8726   int maxSizeOfArr=arrIn->getNumberOfTuples();
8727   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8728   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8729   arrIo->alloc((int)(sz+1),1);
8730   const int *idsIt=idsOfSelectBg;
8731   int *work=arrIo->getPointer();
8732   *work++=0;
8733   int lgth=0;
8734   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8735     {
8736       if(*idsIt>=0 && *idsIt<nbOfGrps)
8737         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8738       else
8739         {
8740           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8741           throw INTERP_KERNEL::Exception(oss.str().c_str());
8742         }
8743       if(lgth>=work[-1])
8744         *work=lgth;
8745       else
8746         {
8747           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8748           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8749           throw INTERP_KERNEL::Exception(oss.str().c_str());
8750         }
8751     }
8752   arro->alloc(lgth,1);
8753   work=arro->getPointer();
8754   idsIt=idsOfSelectBg;
8755   for(std::size_t i=0;i<sz;i++,idsIt++)
8756     {
8757       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8758         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8759       else
8760         {
8761           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8762           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8763           throw INTERP_KERNEL::Exception(oss.str().c_str());
8764         }
8765     }
8766   arrOut=arro.retn();
8767   arrIndexOut=arrIo.retn();
8768 }
8769
8770 /*!
8771  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8772  * 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 ).
8773  * The selection of extraction is done standardly in new2old format.
8774  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8775  *
8776  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8777  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8778  * \param [in] arrIn arr origin array from which the extraction will be done.
8779  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8780  * \param [out] arrOut the resulting array
8781  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8782  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8783  */
8784 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8785                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8786 {
8787   if(!arrIn || !arrIndxIn)
8788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8789   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8790   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8791     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8792   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8793   const int *arrInPtr=arrIn->getConstPointer();
8794   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8795   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8796   if(nbOfGrps<0)
8797     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8798   int maxSizeOfArr=arrIn->getNumberOfTuples();
8799   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8800   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8801   arrIo->alloc((int)(sz+1),1);
8802   int idsIt=idsOfSelectStart;
8803   int *work=arrIo->getPointer();
8804   *work++=0;
8805   int lgth=0;
8806   for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8807     {
8808       if(idsIt>=0 && idsIt<nbOfGrps)
8809         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8810       else
8811         {
8812           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8813           throw INTERP_KERNEL::Exception(oss.str().c_str());
8814         }
8815       if(lgth>=work[-1])
8816         *work=lgth;
8817       else
8818         {
8819           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8820           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8821           throw INTERP_KERNEL::Exception(oss.str().c_str());
8822         }
8823     }
8824   arro->alloc(lgth,1);
8825   work=arro->getPointer();
8826   idsIt=idsOfSelectStart;
8827   for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8828     {
8829       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8830         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8831       else
8832         {
8833           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8834           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8835           throw INTERP_KERNEL::Exception(oss.str().c_str());
8836         }
8837     }
8838   arrOut=arro.retn();
8839   arrIndexOut=arrIo.retn();
8840 }
8841
8842 /*!
8843  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8844  * 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
8845  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8846  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8847  *
8848  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8849  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8850  * \param [in] arrIn arr origin array from which the extraction will be done.
8851  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8852  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8853  * \param [in] srcArrIndex index array of \b srcArr
8854  * \param [out] arrOut the resulting array
8855  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8856  * 
8857  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8858  */
8859 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8860                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8861                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8862 {
8863   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8864     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8866   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8867   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8868   std::vector<bool> v(nbOfTuples,true);
8869   int offset=0;
8870   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8871   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8872   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8873     {
8874       if(*it>=0 && *it<nbOfTuples)
8875         {
8876           v[*it]=false;
8877           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8878         }
8879       else
8880         {
8881           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8882           throw INTERP_KERNEL::Exception(oss.str().c_str());
8883         }
8884     }
8885   srcArrIndexPtr=srcArrIndex->getConstPointer();
8886   arrIo->alloc(nbOfTuples+1,1);
8887   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8888   const int *arrInPtr=arrIn->getConstPointer();
8889   const int *srcArrPtr=srcArr->getConstPointer();
8890   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8891   int *arroPtr=arro->getPointer();
8892   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8893     {
8894       if(v[ii])
8895         {
8896           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8897           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8898         }
8899       else
8900         {
8901           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8902           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8903           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8904         }
8905     }
8906   arrOut=arro.retn();
8907   arrIndexOut=arrIo.retn();
8908 }
8909
8910 /*!
8911  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8912  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8913  *
8914  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8915  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8916  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8917  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8918  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8919  * \param [in] srcArrIndex index array of \b srcArr
8920  * 
8921  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8922  */
8923 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8924                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8925 {
8926   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8927     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8928   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8929   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8930   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8931   int *arrInOutPtr=arrInOut->getPointer();
8932   const int *srcArrPtr=srcArr->getConstPointer();
8933   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8934     {
8935       if(*it>=0 && *it<nbOfTuples)
8936         {
8937           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8938             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8939           else
8940             {
8941               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] !";
8942               throw INTERP_KERNEL::Exception(oss.str().c_str());
8943             }
8944         }
8945       else
8946         {
8947           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8948           throw INTERP_KERNEL::Exception(oss.str().c_str());
8949         }
8950     }
8951 }
8952
8953 /*!
8954  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8955  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8956  * 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]].
8957  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8958  * A negative value in \b arrIn means that it is ignored.
8959  * 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.
8960  * 
8961  * \param [in] arrIn arr origin array from which the extraction will be done.
8962  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8963  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8964  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8965  */
8966 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8967 {
8968   int seed=0,nbOfDepthPeelingPerformed=0;
8969   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8970 }
8971
8972 /*!
8973  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8974  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8975  * 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]].
8976  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8977  * A negative value in \b arrIn means that it is ignored.
8978  * 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.
8979  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8980  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8981  * \param [in] arrIn arr origin array from which the extraction will be done.
8982  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8983  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8984  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8985  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8986  * \sa MEDCouplingUMesh::partitionBySpreadZone
8987  */
8988 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8989 {
8990   nbOfDepthPeelingPerformed=0;
8991   if(!arrIndxIn)
8992     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8993   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8994   if(nbOfTuples<=0)
8995     {
8996       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8997       return ret;
8998     }
8999   //
9000   std::vector<bool> fetched(nbOfTuples,false);
9001   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9002 }
9003
9004 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9005 {
9006   nbOfDepthPeelingPerformed=0;
9007   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9008     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9009   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9010   std::vector<bool> fetched2(nbOfTuples,false);
9011   int i=0;
9012   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9013     {
9014       if(*seedElt>=0 && *seedElt<nbOfTuples)
9015         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9016       else
9017         { std::ostringstream oss; oss << "MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : At pos #" << i << " of seeds value is " << *seedElt << "! Should be in [0," << nbOfTuples << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
9018     }
9019   const int *arrInPtr=arrIn->getConstPointer();
9020   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9021   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9022   std::vector<int> idsToFetch1(seedBg,seedEnd);
9023   std::vector<int> idsToFetch2;
9024   std::vector<int> *idsToFetch=&idsToFetch1;
9025   std::vector<int> *idsToFetchOther=&idsToFetch2;
9026   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9027     {
9028       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9029         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9030           if(!fetched[*it2])
9031             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9032       std::swap(idsToFetch,idsToFetchOther);
9033       idsToFetchOther->clear();
9034       nbOfDepthPeelingPerformed++;
9035     }
9036   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9037   i=0;
9038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9039   int *retPtr=ret->getPointer();
9040   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9041     if(*it)
9042       *retPtr++=i;
9043   return ret.retn();
9044 }
9045
9046 /*!
9047  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9048  * 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
9049  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9050  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9051  *
9052  * \param [in] start begin of set of ids of the input extraction (included)
9053  * \param [in] end end of set of ids of the input extraction (excluded)
9054  * \param [in] step step of the set of ids in range mode.
9055  * \param [in] arrIn arr origin array from which the extraction will be done.
9056  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9057  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9058  * \param [in] srcArrIndex index array of \b srcArr
9059  * \param [out] arrOut the resulting array
9060  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9061  * 
9062  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9063  */
9064 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9065                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9066                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9067 {
9068   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9069     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9070   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9071   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9072   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9073   int offset=0;
9074   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9075   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9076   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9077   int it=start;
9078   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9079     {
9080       if(it>=0 && it<nbOfTuples)
9081         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9082       else
9083         {
9084           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9085           throw INTERP_KERNEL::Exception(oss.str().c_str());
9086         }
9087     }
9088   srcArrIndexPtr=srcArrIndex->getConstPointer();
9089   arrIo->alloc(nbOfTuples+1,1);
9090   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9091   const int *arrInPtr=arrIn->getConstPointer();
9092   const int *srcArrPtr=srcArr->getConstPointer();
9093   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9094   int *arroPtr=arro->getPointer();
9095   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9096     {
9097       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9098       if(pos<0)
9099         {
9100           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9101           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9102         }
9103       else
9104         {
9105           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9106           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9107         }
9108     }
9109   arrOut=arro.retn();
9110   arrIndexOut=arrIo.retn();
9111 }
9112
9113 /*!
9114  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9115  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9116  *
9117  * \param [in] start begin of set of ids of the input extraction (included)
9118  * \param [in] end end of set of ids of the input extraction (excluded)
9119  * \param [in] step step of the set of ids in range mode.
9120  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9121  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9122  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9123  * \param [in] srcArrIndex index array of \b srcArr
9124  * 
9125  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9126  */
9127 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9128                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9129 {
9130   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9131     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9132   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9133   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9134   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9135   int *arrInOutPtr=arrInOut->getPointer();
9136   const int *srcArrPtr=srcArr->getConstPointer();
9137   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9138   int it=start;
9139   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9140     {
9141       if(it>=0 && it<nbOfTuples)
9142         {
9143           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9144             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9145           else
9146             {
9147               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9148               throw INTERP_KERNEL::Exception(oss.str().c_str());
9149             }
9150         }
9151       else
9152         {
9153           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9154           throw INTERP_KERNEL::Exception(oss.str().c_str());
9155         }
9156     }
9157 }
9158
9159 /*!
9160  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9161  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9162  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9163  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9164  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9165  * 
9166  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9167  */
9168 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9169 {
9170   checkFullyDefined();
9171   int mdim=getMeshDimension();
9172   int spaceDim=getSpaceDimension();
9173   if(mdim!=spaceDim)
9174     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9175   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9176   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9177   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9178   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9179   ret->setCoords(getCoords());
9180   ret->allocateCells((int)partition.size());
9181   //
9182   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9183     {
9184       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9185       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9186       switch(mdim)
9187         {
9188         case 2:
9189           cell=tmp->buildUnionOf2DMesh();
9190           break;
9191         case 3:
9192           cell=tmp->buildUnionOf3DMesh();
9193           break;
9194         default:
9195           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9196         }
9197       
9198       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9199     }
9200   //
9201   ret->finishInsertingCells();
9202   return ret.retn();
9203 }
9204
9205 /*!
9206  * This method partitions \b this into contiguous zone.
9207  * This method only needs a well defined connectivity. Coordinates are not considered here.
9208  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9209  */
9210 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9211 {
9212   //#if 0
9213   int nbOfCellsCur=getNumberOfCells();
9214   std::vector<DataArrayInt *> ret;
9215   if(nbOfCellsCur<=0)
9216     return ret;
9217   DataArrayInt *neigh=0,*neighI=0;
9218   computeNeighborsOfCells(neigh,neighI);
9219   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9220   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9221   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9222   int seed=0;
9223   while(seed<nbOfCellsCur)
9224     {
9225       int nbOfPeelPerformed=0;
9226       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9227       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9228     }
9229   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9230     ret.push_back((*it).retn());
9231   return ret;
9232   //#endif
9233 #if 0
9234   int nbOfCellsCur=getNumberOfCells();
9235   DataArrayInt *neigh=0,*neighI=0;
9236   computeNeighborsOfCells(neigh,neighI);
9237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9239   std::vector<DataArrayInt *> ret;
9240   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9241   while(nbOfCellsCur>0)
9242     {
9243       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9244       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9245       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9246       ret2.push_back(tmp2);  ret.push_back(tmp2);
9247       nbOfCellsCur=tmp3->getNumberOfTuples();
9248       if(nbOfCellsCur>0)
9249         {
9250           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9251           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9252           neighAuto=neigh;
9253           neighIAuto=neighI;
9254           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9255           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9256         }
9257     }
9258   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9259     (*it)->incrRef();
9260   return ret;
9261 #endif
9262 }
9263
9264 /*!
9265  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9266  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9267  *
9268  * \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.
9269  * \return a newly allocated DataArrayInt to be managed by the caller.
9270  * \throw In case of \a code has not the right format (typically of size 3*n)
9271  */
9272 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9273 {
9274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9275   std::size_t nb=code.size()/3;
9276   if(code.size()%3!=0)
9277     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9278   ret->alloc((int)nb,2);
9279   int *retPtr=ret->getPointer();
9280   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9281     {
9282       retPtr[0]=code[3*i+2];
9283       retPtr[1]=code[3*i+2]+code[3*i+1];
9284     }
9285   return ret.retn();
9286 }
9287
9288 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9289                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9290 {
9291   if(mesh)
9292     {
9293       mesh->incrRef();
9294       _nb_cell=mesh->getNumberOfCells();
9295     }
9296 }
9297
9298 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9299 {
9300   if(_mesh)
9301     _mesh->decrRef();
9302   if(_own_cell)
9303     delete _cell;
9304 }
9305
9306 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9307                                                                                                                                _own_cell(false),_cell_id(bg-1),
9308                                                                                                                                _nb_cell(end)
9309 {
9310   if(mesh)
9311     mesh->incrRef();
9312 }
9313
9314 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9315 {
9316   _cell_id++;
9317   if(_cell_id<_nb_cell)
9318     {
9319       _cell->next();
9320       return _cell;
9321     }
9322   else
9323     return 0;
9324 }
9325
9326 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9327 {
9328   if(_mesh)
9329     _mesh->incrRef();
9330 }
9331
9332 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9333 {
9334   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9335 }
9336
9337 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9338 {
9339   if(_mesh)
9340     _mesh->decrRef();
9341 }
9342
9343 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9344                                                                                                                                                                   _itc(itc),
9345                                                                                                                                                                   _bg(bg),_end(end)
9346 {
9347   if(_mesh)
9348     _mesh->incrRef();
9349 }
9350
9351 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9352 {
9353   if(_mesh)
9354     _mesh->decrRef();
9355 }
9356
9357 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9358 {
9359   return _type;
9360 }
9361
9362 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9363 {
9364   return _end-_bg;
9365 }
9366
9367 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9368 {
9369   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9370 }
9371
9372 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9373 {
9374   if(mesh)
9375     {
9376       mesh->incrRef();
9377       _nb_cell=mesh->getNumberOfCells();
9378     }
9379 }
9380
9381 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9382 {
9383   if(_mesh)
9384     _mesh->decrRef();
9385   delete _cell;
9386 }
9387
9388 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9389 {
9390   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9391   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9392   if(_cell_id<_nb_cell)
9393     {
9394       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9395       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9396       int startId=_cell_id;
9397       _cell_id+=nbOfElems;
9398       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9399     }
9400   else
9401     return 0;
9402 }
9403
9404 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9405 {
9406   if(mesh)
9407     {
9408       _conn=mesh->getNodalConnectivity()->getPointer();
9409       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9410     }
9411 }
9412
9413 void MEDCouplingUMeshCell::next()
9414 {
9415   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9416     {
9417       _conn+=_conn_lgth;
9418       _conn_indx++;
9419     }
9420   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9421 }
9422
9423 std::string MEDCouplingUMeshCell::repr() const
9424 {
9425   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9426     {
9427       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9428       oss << " : ";
9429       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9430       return oss.str();
9431     }
9432   else
9433     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9434 }
9435
9436 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9437 {
9438   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9439     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9440   else
9441     return INTERP_KERNEL::NORM_ERROR;
9442 }
9443
9444 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9445 {
9446   lgth=_conn_lgth;
9447   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9448     return _conn;
9449   else
9450     return 0;
9451 }