Salome HOME
Generalization of unstructured grid supported by the remapper.
[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  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1395  */
1396 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1397 {
1398   checkConnectivityFullyDefined();
1399   int nbOfCells=getNumberOfCells();
1400   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1401   ret->alloc(nbOfCells,1);
1402   int *retPtr=ret->getPointer();
1403   const int *conn=getNodalConnectivity()->getConstPointer();
1404   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1405   for(int i=0;i<nbOfCells;i++,retPtr++)
1406     {
1407       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1408         *retPtr=connI[i+1]-connI[i]-1;
1409       else
1410         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1411     }
1412   return ret.retn();
1413 }
1414
1415 /*!
1416  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1417  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1418  *
1419  * \return DataArrayInt * - new object to be deallocated by the caller.
1420  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1421  */
1422 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1423 {
1424   checkConnectivityFullyDefined();
1425   int nbOfCells=getNumberOfCells();
1426   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1427   ret->alloc(nbOfCells,1);
1428   int *retPtr=ret->getPointer();
1429   const int *conn=getNodalConnectivity()->getConstPointer();
1430   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1431   for(int i=0;i<nbOfCells;i++,retPtr++)
1432     {
1433       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1434       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1435         *retPtr=(int)s.size();
1436       else
1437         {
1438           s.erase(-1);
1439           *retPtr=(int)s.size();
1440         }
1441     }
1442   return ret.retn();
1443 }
1444
1445 /*!
1446  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1447  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1448  * 
1449  * \return a newly allocated array
1450  */
1451 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1452 {
1453   checkConnectivityFullyDefined();
1454   int nbOfCells=getNumberOfCells();
1455   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1456   ret->alloc(nbOfCells,1);
1457   int *retPtr=ret->getPointer();
1458   const int *conn=getNodalConnectivity()->getConstPointer();
1459   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1460   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1461     {
1462       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1463       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1464     }
1465   return ret.retn();
1466 }
1467
1468 /*!
1469  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1470  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1471  * array mean that the corresponding old node is no more used. 
1472  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1473  *           this->getNumberOfNodes() before call of this method. The caller is to
1474  *           delete this array using decrRef() as it is no more needed. 
1475  *  \throw If the coordinates array is not set.
1476  *  \throw If the nodal connectivity of cells is not defined.
1477  *  \throw If the nodal connectivity includes an invalid id.
1478  *
1479  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1480  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1481  */
1482 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1483 {
1484   return MEDCouplingPointSet::zipCoordsTraducer();
1485 }
1486
1487 /*!
1488  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1489  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1490  */
1491 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1492 {
1493   switch(compType)
1494     {
1495     case 0:
1496       return AreCellsEqual0(conn,connI,cell1,cell2);
1497     case 1:
1498       return AreCellsEqual1(conn,connI,cell1,cell2);
1499     case 2:
1500       return AreCellsEqual2(conn,connI,cell1,cell2);
1501     case 3:
1502       return AreCellsEqual3(conn,connI,cell1,cell2);
1503     case 7:
1504       return AreCellsEqual7(conn,connI,cell1,cell2);
1505     }
1506   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1507 }
1508
1509 /*!
1510  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1511  */
1512 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1513 {
1514   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1515     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1516   return 0;
1517 }
1518
1519 /*!
1520  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1521  */
1522 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1523 {
1524   int sz=connI[cell1+1]-connI[cell1];
1525   if(sz==connI[cell2+1]-connI[cell2])
1526     {
1527       if(conn[connI[cell1]]==conn[connI[cell2]])
1528         {
1529           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1530           unsigned dim=cm.getDimension();
1531           if(dim!=3)
1532             {
1533               if(dim!=1)
1534                 {
1535                   int sz1=2*(sz-1);
1536                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1537                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1538                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1539                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1540                   return work!=tmp+sz1?1:0;
1541                 }
1542               else
1543                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1544             }
1545           else
1546             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1547         }
1548     }
1549   return 0;
1550 }
1551
1552 /*!
1553  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1554  */
1555 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1556 {
1557   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1558     {
1559       if(conn[connI[cell1]]==conn[connI[cell2]])
1560         {
1561           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1562           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1563           return s1==s2?1:0;
1564         }
1565     }
1566   return 0;
1567 }
1568
1569 /*!
1570  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1571  */
1572 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1573 {
1574   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1575     {
1576       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1577       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1578       return s1==s2?1:0;
1579     }
1580   return 0;
1581 }
1582
1583 /*!
1584  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1585  */
1586 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1587 {
1588   int sz=connI[cell1+1]-connI[cell1];
1589   if(sz==connI[cell2+1]-connI[cell2])
1590     {
1591       if(conn[connI[cell1]]==conn[connI[cell2]])
1592         {
1593           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1594           unsigned dim=cm.getDimension();
1595           if(dim!=3)
1596             {
1597               if(dim!=1)
1598                 {
1599                   int sz1=2*(sz-1);
1600                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1601                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1602                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1603                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1604                   if(work!=tmp+sz1)
1605                     return 1;
1606                   else
1607                     {
1608                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1609                       std::reverse_iterator<int *> it2((int *)tmp);
1610                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1611                         return 2;
1612                       else
1613                         return 0;
1614                     }
1615                   
1616                   return work!=tmp+sz1?1:0;
1617                 }
1618               else
1619                 {//case of SEG2 and SEG3
1620                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1621                     return 1;
1622                   if(!cm.isQuadratic())
1623                     {
1624                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1625                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1626                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1627                         return 2;
1628                       return 0;
1629                     }
1630                   else
1631                     {
1632                       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])
1633                         return 2;
1634                       return 0;
1635                     }
1636                 }
1637             }
1638           else
1639             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1640         }
1641     }
1642   return 0;
1643 }
1644
1645 /*!
1646  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1647  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1648  * and result remains unchanged.
1649  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1650  * If in 'candidates' pool -1 value is considered as an empty value.
1651  * WARNING this method returns only ONE set of result !
1652  */
1653 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1654 {
1655   if(candidates.size()<1)
1656     return false;
1657   bool ret=false;
1658   std::vector<int>::const_iterator iter=candidates.begin();
1659   int start=(*iter++);
1660   for(;iter!=candidates.end();iter++)
1661     {
1662       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1663       if(status!=0)
1664         {
1665           if(!ret)
1666             {
1667               result->pushBackSilent(start);
1668               ret=true;
1669             }
1670           if(status==1)
1671             result->pushBackSilent(*iter);
1672           else
1673             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1674         }
1675     }
1676   return ret;
1677 }
1678
1679 /*!
1680  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1681  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1682  *
1683  * \param [in] compType input specifying the technique used to compare cells each other.
1684  *   - 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.
1685  *   - 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)
1686  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1687  *   - 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
1688  * can be used for users not sensitive to orientation of cell
1689  * \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.
1690  * \param [out] commonCells
1691  * \param [out] commonCellsI
1692  * \return the correspondance array old to new in a newly allocated array.
1693  * 
1694  */
1695 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1696 {
1697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1698   getReverseNodalConnectivity(revNodal,revNodalI);
1699   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1700 }
1701
1702 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1703                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1704 {
1705   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1706   int nbOfCells=nodalI->getNumberOfTuples()-1;
1707   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1708   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1709   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1710   std::vector<bool> isFetched(nbOfCells,false);
1711   if(startCellId==0)
1712     {
1713       for(int i=0;i<nbOfCells;i++)
1714         {
1715           if(!isFetched[i])
1716             {
1717               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1718               std::vector<int> v,v2;
1719               if(connOfNode!=connPtr+connIPtr[i+1])
1720                 {
1721                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1722                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1723                   connOfNode++;
1724                 }
1725               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1726                 if(*connOfNode>=0)
1727                   {
1728                     v=v2;
1729                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1730                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1731                     v2.resize(std::distance(v2.begin(),it));
1732                   }
1733               if(v2.size()>1)
1734                 {
1735                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1736                     {
1737                       int pos=commonCellsI->back();
1738                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1739                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1740                         isFetched[*it]=true;
1741                     }
1742                 }
1743             }
1744         }
1745     }
1746   else
1747     {
1748       for(int i=startCellId;i<nbOfCells;i++)
1749         {
1750           if(!isFetched[i])
1751             {
1752               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1753               std::vector<int> v,v2;
1754               if(connOfNode!=connPtr+connIPtr[i+1])
1755                 {
1756                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1757                   connOfNode++;
1758                 }
1759               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1760                 if(*connOfNode>=0)
1761                   {
1762                     v=v2;
1763                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1764                     v2.resize(std::distance(v2.begin(),it));
1765                   }
1766               if(v2.size()>1)
1767                 {
1768                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1769                     {
1770                       int pos=commonCellsI->back();
1771                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1772                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1773                         isFetched[*it]=true;
1774                     }
1775                 }
1776             }
1777         }
1778     }
1779   commonCellsArr=commonCells.retn();
1780   commonCellsIArr=commonCellsI.retn();
1781 }
1782
1783 /*!
1784  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1785  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1786  * than \a other->getNumberOfCells() in the returned array means that there is no
1787  * corresponding cell in \a this mesh.
1788  * It is expected that \a this and \a other meshes share the same node coordinates
1789  * array, if it is not so an exception is thrown. 
1790  *  \param [in] other - the mesh to compare with.
1791  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1792  *         valid values [0,1,2], see zipConnectivityTraducer().
1793  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1794  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1795  *         values. The caller is to delete this array using
1796  *         decrRef() as it is no more needed.
1797  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1798  *         mesh.
1799  *
1800  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1801  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1802  *  \sa checkDeepEquivalOnSameNodesWith()
1803  *  \sa checkGeoEquivalWith()
1804  */
1805 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1806 {
1807   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1808   int nbOfCells=getNumberOfCells();
1809   static const int possibleCompType[]={0,1,2};
1810   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1811     {
1812       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1813       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1814       oss << " !";
1815       throw INTERP_KERNEL::Exception(oss.str().c_str());
1816     }
1817   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1818   arr=o2n->substr(nbOfCells);
1819   arr->setName(other->getName().c_str());
1820   int tmp;
1821   if(other->getNumberOfCells()==0)
1822     return true;
1823   return arr->getMaxValue(tmp)<nbOfCells;
1824 }
1825
1826 /*!
1827  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1828  * This method tries to determine if \b other is fully included in \b this.
1829  * The main difference is that this method is not expected to throw exception.
1830  * This method has two outputs :
1831  *
1832  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1833  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1834  */
1835 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1836 {
1837   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1838   DataArrayInt *commonCells=0,*commonCellsI=0;
1839   int thisNbCells=getNumberOfCells();
1840   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1842   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1843   int otherNbCells=other->getNumberOfCells();
1844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1845   arr2->alloc(otherNbCells,1);
1846   arr2->fillWithZero();
1847   int *arr2Ptr=arr2->getPointer();
1848   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1849   for(int i=0;i<nbOfCommon;i++)
1850     {
1851       int start=commonCellsPtr[commonCellsIPtr[i]];
1852       if(start<thisNbCells)
1853         {
1854           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1855             {
1856               int sig=commonCellsPtr[j]>0?1:-1;
1857               int val=std::abs(commonCellsPtr[j])-1;
1858               if(val>=thisNbCells)
1859                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1860             }
1861         }
1862     }
1863   arr2->setName(other->getName().c_str());
1864   if(arr2->presenceOfValue(0))
1865     return false;
1866   arr=arr2.retn();
1867   return true;
1868 }
1869
1870 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1871 {
1872   if(!other)
1873     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1874   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1875   if(!otherC)
1876     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1877   std::vector<const MEDCouplingUMesh *> ms(2);
1878   ms[0]=this;
1879   ms[1]=otherC;
1880   return MergeUMeshesOnSameCoords(ms);
1881 }
1882
1883 /*!
1884  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1885  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1886  * cellIds is not given explicitely but by a range python like.
1887  * 
1888  * \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.
1889  * \return a newly allocated
1890  * 
1891  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1892  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1893  */
1894 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1895 {
1896   if(getMeshDimension()!=-1)
1897     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1898   else
1899     {
1900       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1901       if(newNbOfCells!=1)
1902         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1903       if(start!=0)
1904         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1905       incrRef();
1906       return const_cast<MEDCouplingUMesh *>(this);
1907     }
1908 }
1909
1910 /*!
1911  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1912  * The result mesh shares or not the node coordinates array with \a this mesh depending
1913  * on \a keepCoords parameter.
1914  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1915  *           to write this mesh to the MED file, its cells must be sorted using
1916  *           sortCellsInMEDFileFrmt().
1917  *  \param [in] begin - an array of cell ids to include to the new mesh.
1918  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1919  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1920  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1921  *         by calling zipCoords().
1922  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1923  *         to delete this mesh using decrRef() as it is no more needed. 
1924  *  \throw If the coordinates array is not set.
1925  *  \throw If the nodal connectivity of cells is not defined.
1926  *  \throw If any cell id in the array \a begin is not valid.
1927  *
1928  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1929  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1930  */
1931 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1932 {
1933   if(getMeshDimension()!=-1)
1934     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1935   else
1936     {
1937       if(end-begin!=1)
1938         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1939       if(begin[0]!=0)
1940         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1941       incrRef();
1942       return const_cast<MEDCouplingUMesh *>(this);
1943     }
1944 }
1945
1946 /*!
1947  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1948  *
1949  * 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.
1950  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1951  * The number of cells of \b this will remain the same with this method.
1952  *
1953  * \param [in] begin begin of cell ids (included) of cells in this to assign
1954  * \param [in] end end of cell ids (excluded) of cells in this to assign
1955  * \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 ).
1956  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1957  */
1958 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1959 {
1960   checkConnectivityFullyDefined();
1961   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1962   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1963     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1964   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1965     {
1966       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1967       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1968       throw INTERP_KERNEL::Exception(oss.str().c_str());
1969     }
1970   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1971   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1972     {
1973       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1974       throw INTERP_KERNEL::Exception(oss.str().c_str());
1975     }
1976   int nbOfCells=getNumberOfCells();
1977   bool easyAssign=true;
1978   const int *connI=_nodal_connec_index->getConstPointer();
1979   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1980   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1981     {
1982       if(*it>=0 && *it<nbOfCells)
1983         {
1984           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1985         }
1986       else
1987         {
1988           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1989           throw INTERP_KERNEL::Exception(oss.str().c_str());
1990         }
1991     }
1992   if(easyAssign)
1993     {
1994       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1995       computeTypes();
1996     }
1997   else
1998     {
1999       DataArrayInt *arrOut=0,*arrIOut=0;
2000       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2001                                                arrOut,arrIOut);
2002       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2003       setConnectivity(arrOut,arrIOut,true);
2004     }
2005 }
2006
2007 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2008 {
2009   checkConnectivityFullyDefined();
2010   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2011   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2012     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2013   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2014     {
2015       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2016       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2017       throw INTERP_KERNEL::Exception(oss.str().c_str());
2018     }
2019   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2020   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2021     {
2022       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2023       throw INTERP_KERNEL::Exception(oss.str().c_str());
2024     }
2025   int nbOfCells=getNumberOfCells();
2026   bool easyAssign=true;
2027   const int *connI=_nodal_connec_index->getConstPointer();
2028   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2029   int it=start;
2030   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2031     {
2032       if(it>=0 && it<nbOfCells)
2033         {
2034           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2035         }
2036       else
2037         {
2038           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2039           throw INTERP_KERNEL::Exception(oss.str().c_str());
2040         }
2041     }
2042   if(easyAssign)
2043     {
2044       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2045       computeTypes();
2046     }
2047   else
2048     {
2049       DataArrayInt *arrOut=0,*arrIOut=0;
2050       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2051                                                 arrOut,arrIOut);
2052       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2053       setConnectivity(arrOut,arrIOut,true);
2054     }
2055 }                      
2056
2057 /*!
2058  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2059  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2060  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2061  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2062  *
2063  * \param [in] begin input start of array of node ids.
2064  * \param [in] end input end of array of node ids.
2065  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2066  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2067  */
2068 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2069 {
2070   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2071   checkConnectivityFullyDefined();
2072   int tmp=-1;
2073   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2074   std::vector<bool> fastFinder(sz,false);
2075   for(const int *work=begin;work!=end;work++)
2076     if(*work>=0 && *work<sz)
2077       fastFinder[*work]=true;
2078   int nbOfCells=getNumberOfCells();
2079   const int *conn=getNodalConnectivity()->getConstPointer();
2080   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2081   for(int i=0;i<nbOfCells;i++)
2082     {
2083       int ref=0,nbOfHit=0;
2084       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2085         if(*work2>=0)
2086           {
2087             ref++;
2088             if(fastFinder[*work2])
2089               nbOfHit++;
2090           }
2091       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2092         cellIdsKept->pushBackSilent(i);
2093     }
2094   cellIdsKeptArr=cellIdsKept.retn();
2095 }
2096
2097 /*!
2098  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2099  * this->getMeshDimension(), that bound some cells of \a this mesh.
2100  * The cells of lower dimension to include to the result mesh are selected basing on
2101  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2102  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2103  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2104  * created mesh shares the node coordinates array with \a this mesh. 
2105  *  \param [in] begin - the array of node ids.
2106  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2107  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2108  *         array \a begin are added, else cells whose any node is in the
2109  *         array \a begin are added.
2110  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2111  *         to delete this mesh using decrRef() as it is no more needed. 
2112  *  \throw If the coordinates array is not set.
2113  *  \throw If the nodal connectivity of cells is not defined.
2114  *  \throw If any node id in \a begin is not valid.
2115  *
2116  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2117  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2118  */
2119 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2120 {
2121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2122   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2123   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2124   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2125   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2126 }
2127
2128 /*!
2129  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2130  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2131  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2132  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2133  *         by calling zipCoords().
2134  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2135  *         to delete this mesh using decrRef() as it is no more needed. 
2136  *  \throw If the coordinates array is not set.
2137  *  \throw If the nodal connectivity of cells is not defined.
2138  *
2139  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2140  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2141  */
2142 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2143 {
2144   DataArrayInt *desc=DataArrayInt::New();
2145   DataArrayInt *descIndx=DataArrayInt::New();
2146   DataArrayInt *revDesc=DataArrayInt::New();
2147   DataArrayInt *revDescIndx=DataArrayInt::New();
2148   //
2149   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2150   revDesc->decrRef();
2151   desc->decrRef();
2152   descIndx->decrRef();
2153   int nbOfCells=meshDM1->getNumberOfCells();
2154   const int *revDescIndxC=revDescIndx->getConstPointer();
2155   std::vector<int> boundaryCells;
2156   for(int i=0;i<nbOfCells;i++)
2157     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2158       boundaryCells.push_back(i);
2159   revDescIndx->decrRef();
2160   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2161   return ret;
2162 }
2163
2164 /*!
2165  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2166  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2167  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2168  */
2169 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2170 {
2171   checkFullyDefined();
2172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2176   //
2177   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2178   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2179   //
2180   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2181   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2182   const int *revDescPtr=revDesc->getConstPointer();
2183   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2184   int nbOfCells=getNumberOfCells();
2185   std::vector<bool> ret1(nbOfCells,false);
2186   int sz=0;
2187   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2188     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2189       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2190   //
2191   DataArrayInt *ret2=DataArrayInt::New();
2192   ret2->alloc(sz,1);
2193   int *ret2Ptr=ret2->getPointer();
2194   sz=0;
2195   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2196     if(*it)
2197       *ret2Ptr++=sz;
2198   ret2->setName("BoundaryCells");
2199   return ret2;
2200 }
2201
2202 /*!
2203  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2204  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2205  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2206  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2207  *
2208  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2209  * This method method returns cells ids set s = s1 + s2 where :
2210  * 
2211  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2212  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2213  *
2214  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2215  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2216  *
2217  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2218  * \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
2219  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2220  */
2221 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2222 {
2223   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2224     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2225   checkConnectivityFullyDefined();
2226   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2227   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2228     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2229   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2230   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2231   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2232   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2233   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2234   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2235   DataArrayInt *idsOtherInConsti=0;
2236   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2238   if(!b)
2239     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2240   std::set<int> s1;
2241   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2242     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2245   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2246   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2247   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2248   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2249   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2250   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2251   neighThisPartAuto=0;
2252   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2253   const int li[2]={0,1};
2254   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2255   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2256   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2257   s_renum1->sort();
2258   //
2259   cellIdsRk0=s0arr.retn();
2260   cellIdsRk1=s_renum1.retn();
2261 }
2262
2263 /*!
2264  * 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
2265  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2266  * 
2267  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2268  */
2269 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2270 {
2271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2275   //
2276   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2277   revDesc=0; desc=0; descIndx=0;
2278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2280   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2281 }
2282
2283 /*!
2284  * Finds nodes lying on the boundary of \a this mesh.
2285  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2286  *          nodes. The caller is to delete this array using decrRef() as it is no
2287  *          more needed.
2288  *  \throw If the coordinates array is not set.
2289  *  \throw If the nodal connectivity of cells is node defined.
2290  *
2291  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2292  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2293  */
2294 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2295 {
2296   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2297   return skin->computeFetchedNodeIds();
2298 }
2299
2300 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2301 {
2302   incrRef();
2303   return const_cast<MEDCouplingUMesh *>(this);
2304 }
2305
2306 /*!
2307  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2308  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2309  * 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.
2310  * 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.
2311  * 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.
2312  *
2313  * \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
2314  *             parameter is altered during the call.
2315  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2316  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2317  * \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.
2318  *
2319  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2320  */
2321 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2322                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2323 {
2324   checkFullyDefined();
2325   otherDimM1OnSameCoords.checkFullyDefined();
2326   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2327     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2328   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2329     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2330   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2331   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2333   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2334   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2335   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2339   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2340   //
2341   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2342   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2343   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2344   DataArrayInt *idsTmp=0;
2345   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2347   if(!b)
2348     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2349   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2350   DataArrayInt *tmp0=0,*tmp1=0;
2351   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2352   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2353   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2354   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2356   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2357   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2358   //
2359   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2360   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2361   nodeIdsToDuplicate=s3.retn();
2362 }
2363
2364 /*!
2365  * This method operates a modification of the connectivity and coords in \b this.
2366  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2367  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2368  * 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
2369  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2370  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2371  * 
2372  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2373  * 
2374  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2375  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2376  */
2377 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2378 {
2379   int nbOfNodes=getNumberOfNodes();
2380   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2381   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2382 }
2383
2384 /*!
2385  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2386  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2387  * This method is a generalization of shiftNodeNumbersInConn().
2388  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2389  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2390  *         this->getNumberOfNodes(), in "Old to New" mode. 
2391  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2392  *  \throw If the nodal connectivity of cells is not defined.
2393  *
2394  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2395  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2396  */
2397 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2398 {
2399   checkConnectivityFullyDefined();
2400   int *conn=getNodalConnectivity()->getPointer();
2401   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2402   int nbOfCells=getNumberOfCells();
2403   for(int i=0;i<nbOfCells;i++)
2404     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2405       {
2406         int& node=conn[iconn];
2407         if(node>=0)//avoid polyhedron separator
2408           {
2409             node=newNodeNumbersO2N[node];
2410           }
2411       }
2412   _nodal_connec->declareAsNew();
2413   updateTime();
2414 }
2415
2416 /*!
2417  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2418  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2419  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2420  * 
2421  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2422  */
2423 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2424 {
2425   checkConnectivityFullyDefined();
2426   int *conn=getNodalConnectivity()->getPointer();
2427   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2428   int nbOfCells=getNumberOfCells();
2429   for(int i=0;i<nbOfCells;i++)
2430     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2431       {
2432         int& node=conn[iconn];
2433         if(node>=0)//avoid polyhedron separator
2434           {
2435             node+=delta;
2436           }
2437       }
2438   _nodal_connec->declareAsNew();
2439   updateTime();
2440 }
2441
2442 /*!
2443  * This method operates a modification of the connectivity in \b this.
2444  * 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.
2445  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2446  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2447  * 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
2448  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2449  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2450  * 
2451  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2452  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2453  * 
2454  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2455  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2456  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2457  */
2458 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2459 {
2460   checkConnectivityFullyDefined();
2461   std::map<int,int> m;
2462   int val=offset;
2463   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2464     m[*work]=val;
2465   int *conn=getNodalConnectivity()->getPointer();
2466   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2467   int nbOfCells=getNumberOfCells();
2468   for(int i=0;i<nbOfCells;i++)
2469     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2470       {
2471         int& node=conn[iconn];
2472         if(node>=0)//avoid polyhedron separator
2473           {
2474             std::map<int,int>::iterator it=m.find(node);
2475             if(it!=m.end())
2476               node=(*it).second;
2477           }
2478       }
2479   updateTime();
2480 }
2481
2482 /*!
2483  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2484  *
2485  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2486  * After the call of this method the number of cells remains the same as before.
2487  *
2488  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2489  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2490  * be strictly in [0;this->getNumberOfCells()).
2491  *
2492  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2493  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2494  * should be contained in[0;this->getNumberOfCells()).
2495  * 
2496  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2497  */
2498 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2499 {
2500   checkConnectivityFullyDefined();
2501   int nbCells=getNumberOfCells();
2502   const int *array=old2NewBg;
2503   if(check)
2504     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2505   //
2506   const int *conn=_nodal_connec->getConstPointer();
2507   const int *connI=_nodal_connec_index->getConstPointer();
2508   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2509   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2510   const int *n2oPtr=n2o->begin();
2511   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2512   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2513   newConn->copyStringInfoFrom(*_nodal_connec);
2514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2515   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2516   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2517   //
2518   int *newC=newConn->getPointer();
2519   int *newCI=newConnI->getPointer();
2520   int loc=0;
2521   newCI[0]=loc;
2522   for(int i=0;i<nbCells;i++)
2523     {
2524       int pos=n2oPtr[i];
2525       int nbOfElts=connI[pos+1]-connI[pos];
2526       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2527       loc+=nbOfElts;
2528       newCI[i+1]=loc;
2529     }
2530   //
2531   setConnectivity(newConn,newConnI);
2532   if(check)
2533     free(const_cast<int *>(array));
2534 }
2535
2536 /*!
2537  * Finds cells whose bounding boxes intersect a given bounding box.
2538  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2539  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2540  *         zMax (if in 3D). 
2541  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2542  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2543  *         extent of the bounding box of cell to produce an addition to this bounding box.
2544  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2545  *         cells. The caller is to delete this array using decrRef() as it is no more
2546  *         needed. 
2547  *  \throw If the coordinates array is not set.
2548  *  \throw If the nodal connectivity of cells is not defined.
2549  *
2550  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2551  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2552  */
2553 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2554 {
2555   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2556   if(getMeshDimension()==-1)
2557     {
2558       elems->pushBackSilent(0);
2559       return elems.retn();
2560     }
2561   int dim=getSpaceDimension();
2562   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2563   const int* conn      = getNodalConnectivity()->getConstPointer();
2564   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2565   const double* coords = getCoords()->getConstPointer();
2566   int nbOfCells=getNumberOfCells();
2567   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2568     {
2569       for (int i=0; i<dim; i++)
2570         {
2571           elem_bb[i*2]=std::numeric_limits<double>::max();
2572           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2573         }
2574
2575       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2576         {
2577           int node= conn[inode];
2578           if(node>=0)//avoid polyhedron separator
2579             {
2580               for (int idim=0; idim<dim; idim++)
2581                 {
2582                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2583                     {
2584                       elem_bb[idim*2] = coords[node*dim+idim] ;
2585                     }
2586                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2587                     {
2588                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2589                     }
2590                 }
2591             }
2592         }
2593       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2594         elems->pushBackSilent(ielem);
2595     }
2596   return elems.retn();
2597 }
2598
2599 /*!
2600  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2601  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2602  * added in 'elems' parameter.
2603  */
2604 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2605 {
2606   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2607   if(getMeshDimension()==-1)
2608     {
2609       elems->pushBackSilent(0);
2610       return elems.retn();
2611     }
2612   int dim=getSpaceDimension();
2613   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2614   const int* conn      = getNodalConnectivity()->getConstPointer();
2615   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2616   const double* coords = getCoords()->getConstPointer();
2617   int nbOfCells=getNumberOfCells();
2618   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2619     {
2620       for (int i=0; i<dim; i++)
2621         {
2622           elem_bb[i*2]=std::numeric_limits<double>::max();
2623           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2624         }
2625
2626       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2627         {
2628           int node= conn[inode];
2629           if(node>=0)//avoid polyhedron separator
2630             {
2631               for (int idim=0; idim<dim; idim++)
2632                 {
2633                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2634                     {
2635                       elem_bb[idim*2] = coords[node*dim+idim] ;
2636                     }
2637                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2638                     {
2639                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2640                     }
2641                 }
2642             }
2643         }
2644       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2645         elems->pushBackSilent(ielem);
2646     }
2647   return elems.retn();
2648 }
2649
2650 /*!
2651  * Returns a type of a cell by its id.
2652  *  \param [in] cellId - the id of the cell of interest.
2653  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2654  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2655  */
2656 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2657 {
2658   const int *ptI=_nodal_connec_index->getConstPointer();
2659   const int *pt=_nodal_connec->getConstPointer();
2660   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2661     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2662   else
2663     {
2664       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2665       throw INTERP_KERNEL::Exception(oss.str().c_str());
2666     }
2667 }
2668
2669 /*!
2670  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2671  * This method does not throw exception if geometric type \a type is not in \a this.
2672  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2673  * The coordinates array is not considered here.
2674  *
2675  * \param [in] type the geometric type
2676  * \return cell ids in this having geometric type \a type.
2677  */
2678 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2679 {
2680   
2681   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2682   ret->alloc(0,1);
2683   checkConnectivityFullyDefined();
2684   int nbCells=getNumberOfCells();
2685   int mdim=getMeshDimension();
2686   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2687   if(mdim!=(int)cm.getDimension())
2688     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2689   const int *ptI=_nodal_connec_index->getConstPointer();
2690   const int *pt=_nodal_connec->getConstPointer();
2691   for(int i=0;i<nbCells;i++)
2692     {
2693       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2694         ret->pushBackSilent(i);
2695     }
2696   return ret.retn();
2697 }
2698
2699 /*!
2700  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2701  */
2702 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2703 {
2704   const int *ptI=_nodal_connec_index->getConstPointer();
2705   const int *pt=_nodal_connec->getConstPointer();
2706   int nbOfCells=getNumberOfCells();
2707   int ret=0;
2708   for(int i=0;i<nbOfCells;i++)
2709     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2710       ret++;
2711   return ret;
2712 }
2713
2714 /*!
2715  * Returns the nodal connectivity of a given cell.
2716  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2717  * all returned node ids can be used in getCoordinatesOfNode().
2718  *  \param [in] cellId - an id of the cell of interest.
2719  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2720  *         cleared before the appending.
2721  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2722  */
2723 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2724 {
2725   const int *ptI=_nodal_connec_index->getConstPointer();
2726   const int *pt=_nodal_connec->getConstPointer();
2727   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2728     if(*w>=0)
2729       conn.push_back(*w);
2730 }
2731
2732 std::string MEDCouplingUMesh::simpleRepr() const
2733 {
2734   static const char msg0[]="No coordinates specified !";
2735   std::ostringstream ret;
2736   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2737   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2738   int tmpp1,tmpp2;
2739   double tt=getTime(tmpp1,tmpp2);
2740   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2741   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2742   if(_mesh_dim>=-1)
2743     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2744   else
2745     { ret << " Mesh dimension has not been set or is invalid !"; }
2746   if(_coords!=0)
2747     {
2748       const int spaceDim=getSpaceDimension();
2749       ret << spaceDim << "\nInfo attached on space dimension : ";
2750       for(int i=0;i<spaceDim;i++)
2751         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2752       ret << "\n";
2753     }
2754   else
2755     ret << msg0 << "\n";
2756   ret << "Number of nodes : ";
2757   if(_coords!=0)
2758     ret << getNumberOfNodes() << "\n";
2759   else
2760     ret << msg0 << "\n";
2761   ret << "Number of cells : ";
2762   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2763     ret << getNumberOfCells() << "\n";
2764   else
2765     ret << "No connectivity specified !" << "\n";
2766   ret << "Cell types present : ";
2767   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2768     {
2769       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2770       ret << cm.getRepr() << " ";
2771     }
2772   ret << "\n";
2773   return ret.str();
2774 }
2775
2776 std::string MEDCouplingUMesh::advancedRepr() const
2777 {
2778   std::ostringstream ret;
2779   ret << simpleRepr();
2780   ret << "\nCoordinates array : \n___________________\n\n";
2781   if(_coords)
2782     _coords->reprWithoutNameStream(ret);
2783   else
2784     ret << "No array set !\n";
2785   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2786   reprConnectivityOfThisLL(ret);
2787   return ret.str();
2788 }
2789
2790 /*!
2791  * This method returns a C++ code that is a dump of \a this.
2792  * This method will throw if this is not fully defined.
2793  */
2794 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2795 {
2796   static const char coordsName[]="coords";
2797   static const char connName[]="conn";
2798   static const char connIName[]="connI";
2799   checkFullyDefined();
2800   std::ostringstream ret; ret << "// coordinates" << std::endl;
2801   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2802   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2803   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2804   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2805   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2806   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2807   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2808   return ret.str();
2809 }
2810
2811 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2812 {
2813   std::ostringstream ret;
2814   reprConnectivityOfThisLL(ret);
2815   return ret.str();
2816 }
2817
2818 /*!
2819  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2820  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2821  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2822  * some algos).
2823  * 
2824  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2825  * 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
2826  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2827  */
2828 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2829 {
2830   int mdim=getMeshDimension();
2831   if(mdim<0)
2832     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2833   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
2834   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2835   bool needToCpyCT=true;
2836   if(!_nodal_connec)
2837     {
2838       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2839       needToCpyCT=false;
2840     }
2841   else
2842     {
2843       tmp1=_nodal_connec;
2844       tmp1->incrRef();
2845     }
2846   if(!_nodal_connec_index)
2847     {
2848       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2849       needToCpyCT=false;
2850     }
2851   else
2852     {
2853       tmp2=_nodal_connec_index;
2854       tmp2->incrRef();
2855     }
2856   ret->setConnectivity(tmp1,tmp2,false);
2857   if(needToCpyCT)
2858     ret->_types=_types;
2859   if(!_coords)
2860     {
2861       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2862       ret->setCoords(coords);
2863     }
2864   else
2865     ret->setCoords(_coords);
2866   return ret.retn();
2867 }
2868
2869 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2870 {
2871   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2872     {
2873       int nbOfCells=getNumberOfCells();
2874       const int *c=_nodal_connec->getConstPointer();
2875       const int *ci=_nodal_connec_index->getConstPointer();
2876       for(int i=0;i<nbOfCells;i++)
2877         {
2878           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2879           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2880           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2881           stream << "\n";
2882         }
2883     }
2884   else
2885     stream << "Connectivity not defined !\n";
2886 }
2887
2888 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2889 {
2890   const int *ptI=_nodal_connec_index->getConstPointer();
2891   const int *pt=_nodal_connec->getConstPointer();
2892   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2893     return ptI[cellId+1]-ptI[cellId]-1;
2894   else
2895     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2896 }
2897
2898 /*!
2899  * Returns types of cells of the specified part of \a this mesh.
2900  * This method avoids computing sub-mesh explicitely to get its types.
2901  *  \param [in] begin - an array of cell ids of interest.
2902  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2903  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2904  *         describing the cell types. 
2905  *  \throw If the coordinates array is not set.
2906  *  \throw If the nodal connectivity of cells is not defined.
2907  *  \sa getAllTypes()
2908  */
2909 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2910 {
2911   checkFullyDefined();
2912   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2913   const int *conn=_nodal_connec->getConstPointer();
2914   const int *connIndex=_nodal_connec_index->getConstPointer();
2915   for(const int *w=begin;w!=end;w++)
2916     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2917   return ret;
2918 }
2919
2920 /*!
2921  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2922  * a set of types of cells constituting \a this mesh. 
2923  * This method is for advanced users having prepared their connectivity before. For
2924  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2925  *  \param [in] conn - the nodal connectivity array. 
2926  *  \param [in] connIndex - the nodal connectivity index array.
2927  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2928  *         mesh is updated.
2929  */
2930 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2931 {
2932   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2933   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2934   if(isComputingTypes)
2935     computeTypes();
2936   declareAsNew();
2937 }
2938
2939 /*!
2940  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2941  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2942  */
2943 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2944                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2945                                                                                 _types(other._types)
2946 {
2947   if(other._nodal_connec)
2948     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2949   if(other._nodal_connec_index)
2950     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2951 }
2952
2953 MEDCouplingUMesh::~MEDCouplingUMesh()
2954 {
2955   if(_nodal_connec)
2956     _nodal_connec->decrRef();
2957   if(_nodal_connec_index)
2958     _nodal_connec_index->decrRef();
2959 }
2960
2961 /*!
2962  * Recomputes a set of cell types of \a this mesh. For more info see
2963  * \ref MEDCouplingUMeshNodalConnectivity.
2964  */
2965 void MEDCouplingUMesh::computeTypes()
2966 {
2967   if(_nodal_connec && _nodal_connec_index)
2968     {
2969       _types.clear();
2970       const int *conn=_nodal_connec->getConstPointer();
2971       const int *connIndex=_nodal_connec_index->getConstPointer();
2972       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2973       if (nbOfElem > 0)
2974         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2975           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2976     }
2977 }
2978
2979 /*!
2980  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2981  */
2982 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2983 {
2984   if(!_nodal_connec_index || !_nodal_connec || !_coords)
2985     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2986 }
2987
2988 /*!
2989  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2990  */
2991 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2992 {
2993   if(!_nodal_connec_index || !_nodal_connec)
2994     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2995 }
2996
2997 /*!
2998  * Returns a number of cells constituting \a this mesh. 
2999  *  \return int - the number of cells in \a this mesh.
3000  *  \throw If the nodal connectivity of cells is not defined.
3001  */
3002 int MEDCouplingUMesh::getNumberOfCells() const
3003
3004   if(_nodal_connec_index)
3005     return _nodal_connec_index->getNumberOfTuples()-1;
3006   else
3007     if(_mesh_dim==-1)
3008       return 1;
3009     else
3010       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3011 }
3012
3013 /*!
3014  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3015  * mesh. For more info see \ref MEDCouplingMeshesPage.
3016  *  \return int - the dimension of \a this mesh.
3017  *  \throw If the mesh dimension is not defined using setMeshDimension().
3018  */
3019 int MEDCouplingUMesh::getMeshDimension() const
3020 {
3021   if(_mesh_dim<-1)
3022     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3023   return _mesh_dim;
3024 }
3025
3026 /*!
3027  * Returns a length of the nodal connectivity array.
3028  * This method is for test reason. Normally the integer returned is not useable by
3029  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3030  *  \return int - the length of the nodal connectivity array.
3031  */
3032 int MEDCouplingUMesh::getMeshLength() const
3033 {
3034   return _nodal_connec->getNbOfElems();
3035 }
3036
3037 /*!
3038  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3039  */
3040 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3041 {
3042   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3043   tinyInfo.push_back(getMeshDimension());
3044   tinyInfo.push_back(getNumberOfCells());
3045   if(_nodal_connec)
3046     tinyInfo.push_back(getMeshLength());
3047   else
3048     tinyInfo.push_back(-1);
3049 }
3050
3051 /*!
3052  * First step of unserialization process.
3053  */
3054 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3055 {
3056   return tinyInfo[6]<=0;
3057 }
3058
3059 /*!
3060  * Second step of serialization process.
3061  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3062  */
3063 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3064 {
3065   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3066   if(tinyInfo[5]!=-1)
3067     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3068 }
3069
3070 /*!
3071  * Third and final step of serialization process.
3072  */
3073 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3074 {
3075   MEDCouplingPointSet::serialize(a1,a2);
3076   if(getMeshDimension()>-1)
3077     {
3078       a1=DataArrayInt::New();
3079       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3080       int *ptA1=a1->getPointer();
3081       const int *conn=getNodalConnectivity()->getConstPointer();
3082       const int *index=getNodalConnectivityIndex()->getConstPointer();
3083       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3084       std::copy(conn,conn+getMeshLength(),ptA1);
3085     }
3086   else
3087     a1=0;
3088 }
3089
3090 /*!
3091  * Second and final unserialization process.
3092  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3093  */
3094 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3095 {
3096   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3097   setMeshDimension(tinyInfo[5]);
3098   if(tinyInfo[7]!=-1)
3099     {
3100       // Connectivity
3101       const int *recvBuffer=a1->getConstPointer();
3102       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3103       myConnecIndex->alloc(tinyInfo[6]+1,1);
3104       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3105       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3106       myConnec->alloc(tinyInfo[7],1);
3107       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3108       setConnectivity(myConnec, myConnecIndex);
3109     }
3110 }
3111
3112 /*!
3113  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3114  * CellIds are given using range specified by a start an end and step.
3115  */
3116 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3117 {
3118   checkFullyDefined();
3119   int ncell=getNumberOfCells();
3120   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3121   ret->_mesh_dim=_mesh_dim;
3122   ret->setCoords(_coords);
3123   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3124   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3125   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3126   int work=start;
3127   const int *conn=_nodal_connec->getConstPointer();
3128   const int *connIndex=_nodal_connec_index->getConstPointer();
3129   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3130     {
3131       if(work>=0 && work<ncell)
3132         {
3133           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3134         }
3135       else
3136         {
3137           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3138           throw INTERP_KERNEL::Exception(oss.str().c_str());
3139         }
3140     }
3141   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3142   int *newConnPtr=newConn->getPointer();
3143   std::set<INTERP_KERNEL::NormalizedCellType> types;
3144   work=start;
3145   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3146     {
3147       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3148       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3149     }
3150   ret->setConnectivity(newConn,newConnI,false);
3151   ret->_types=types;
3152   ret->copyTinyInfoFrom(this);
3153   return ret.retn();
3154 }
3155
3156 /*!
3157  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3158  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3159  * The return newly allocated mesh will share the same coordinates as \a this.
3160  */
3161 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3162 {
3163   checkConnectivityFullyDefined();
3164   int ncell=getNumberOfCells();
3165   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3166   ret->_mesh_dim=_mesh_dim;
3167   ret->setCoords(_coords);
3168   std::size_t nbOfElemsRet=std::distance(begin,end);
3169   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3170   connIndexRet[0]=0;
3171   const int *conn=_nodal_connec->getConstPointer();
3172   const int *connIndex=_nodal_connec_index->getConstPointer();
3173   int newNbring=0;
3174   for(const int *work=begin;work!=end;work++,newNbring++)
3175     {
3176       if(*work>=0 && *work<ncell)
3177         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3178       else
3179         {
3180           free(connIndexRet);
3181           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3182           throw INTERP_KERNEL::Exception(oss.str().c_str());
3183         }
3184     }
3185   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3186   int *connRetWork=connRet;
3187   std::set<INTERP_KERNEL::NormalizedCellType> types;
3188   for(const int *work=begin;work!=end;work++)
3189     {
3190       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3191       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3192     }
3193   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3194   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3195   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3196   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3197   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3198   ret->_types=types;
3199   ret->copyTinyInfoFrom(this);
3200   return ret.retn();
3201 }
3202
3203 /*!
3204  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3205  * mesh.<br>
3206  * For 1D cells, the returned field contains lengths.<br>
3207  * For 2D cells, the returned field contains areas.<br>
3208  * For 3D cells, the returned field contains volumes.
3209  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3210  *         orientation, i.e. the volume is always positive.
3211  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3212  *         and one time . The caller is to delete this field using decrRef() as it is no
3213  *         more needed.
3214  */
3215 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3216 {
3217   std::string name="MeasureOfMesh_";
3218   name+=getName();
3219   int nbelem=getNumberOfCells();
3220   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3221   field->setName(name.c_str());
3222   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3223   array->alloc(nbelem,1);
3224   double *area_vol=array->getPointer();
3225   field->setArray(array) ; array=0;
3226   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3227   field->synchronizeTimeWithMesh();
3228   if(getMeshDimension()!=-1)
3229     {
3230       int ipt;
3231       INTERP_KERNEL::NormalizedCellType type;
3232       int dim_space=getSpaceDimension();
3233       const double *coords=getCoords()->getConstPointer();
3234       const int *connec=getNodalConnectivity()->getConstPointer();
3235       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3236       for(int iel=0;iel<nbelem;iel++)
3237         {
3238           ipt=connec_index[iel];
3239           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3240           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);
3241         }
3242       if(isAbs)
3243         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3244     }
3245   else
3246     {
3247       area_vol[0]=std::numeric_limits<double>::max();
3248     }
3249   return field.retn();
3250 }
3251
3252 /*!
3253  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3254  * mesh.<br>
3255  * For 1D cells, the returned array contains lengths.<br>
3256  * For 2D cells, the returned array contains areas.<br>
3257  * For 3D cells, the returned array contains volumes.
3258  * This method avoids building explicitly a part of \a this mesh to perform the work.
3259  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3260  *         orientation, i.e. the volume is always positive.
3261  *  \param [in] begin - an array of cell ids of interest.
3262  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3263  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3264  *          delete this array using decrRef() as it is no more needed.
3265  * 
3266  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3267  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3268  *  \sa getMeasureField()
3269  */
3270 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3271 {
3272   std::string name="PartMeasureOfMesh_";
3273   name+=getName();
3274   int nbelem=(int)std::distance(begin,end);
3275   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3276   array->setName(name.c_str());
3277   array->alloc(nbelem,1);
3278   double *area_vol=array->getPointer();
3279   if(getMeshDimension()!=-1)
3280     {
3281       int ipt;
3282       INTERP_KERNEL::NormalizedCellType type;
3283       int dim_space=getSpaceDimension();
3284       const double *coords=getCoords()->getConstPointer();
3285       const int *connec=getNodalConnectivity()->getConstPointer();
3286       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3287       for(const int *iel=begin;iel!=end;iel++)
3288         {
3289           ipt=connec_index[*iel];
3290           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3291           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3292         }
3293       if(isAbs)
3294         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3295     }
3296   else
3297     {
3298       area_vol[0]=std::numeric_limits<double>::max();
3299     }
3300   return array.retn();
3301 }
3302
3303 /*!
3304  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3305  * \a this one. The returned field contains the dual cell volume for each corresponding
3306  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3307  *  the dual mesh in P1 sens of \a this.<br>
3308  * For 1D cells, the returned field contains lengths.<br>
3309  * For 2D cells, the returned field contains areas.<br>
3310  * For 3D cells, the returned field contains volumes.
3311  * This method is useful to check "P1*" conservative interpolators.
3312  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3313  *         orientation, i.e. the volume is always positive.
3314  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3315  *          nodes and one time. The caller is to delete this array using decrRef() as
3316  *          it is no more needed.
3317  */
3318 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3319 {
3320   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3321   std::string name="MeasureOnNodeOfMesh_";
3322   name+=getName();
3323   int nbNodes=getNumberOfNodes();
3324   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3325   double cst=1./((double)getMeshDimension()+1.);
3326   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3327   array->alloc(nbNodes,1);
3328   double *valsToFill=array->getPointer();
3329   std::fill(valsToFill,valsToFill+nbNodes,0.);
3330   const double *values=tmp->getArray()->getConstPointer();
3331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3333   getReverseNodalConnectivity(da,daInd);
3334   const int *daPtr=da->getConstPointer();
3335   const int *daIPtr=daInd->getConstPointer();
3336   for(int i=0;i<nbNodes;i++)
3337     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3338       valsToFill[i]+=cst*values[*cell];
3339   ret->setMesh(this);
3340   ret->setArray(array);
3341   return ret.retn();
3342 }
3343
3344 /*!
3345  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3346  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3347  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3348  * and are normalized.
3349  * <br> \a this can be either 
3350  * - a  2D mesh in 2D or 3D space or 
3351  * - an 1D mesh in 2D space.
3352  * 
3353  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3354  *          cells and one time. The caller is to delete this field using decrRef() as
3355  *          it is no more needed.
3356  *  \throw If the nodal connectivity of cells is not defined.
3357  *  \throw If the coordinates array is not set.
3358  *  \throw If the mesh dimension is not set.
3359  *  \throw If the mesh and space dimension is not as specified above.
3360  */
3361 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3362 {
3363   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3364     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3365   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3366   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3367   int nbOfCells=getNumberOfCells();
3368   int nbComp=getMeshDimension()+1;
3369   array->alloc(nbOfCells,nbComp);
3370   double *vals=array->getPointer();
3371   const int *connI=_nodal_connec_index->getConstPointer();
3372   const int *conn=_nodal_connec->getConstPointer();
3373   const double *coords=_coords->getConstPointer();
3374   if(getMeshDimension()==2)
3375     {
3376       if(getSpaceDimension()==3)
3377         {
3378           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3379           const double *locPtr=loc->getConstPointer();
3380           for(int i=0;i<nbOfCells;i++,vals+=3)
3381             {
3382               int offset=connI[i];
3383               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3384               double n=INTERP_KERNEL::norm<3>(vals);
3385               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3386             }
3387         }
3388       else
3389         {
3390           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3391           const double *isAbsPtr=isAbs->getArray()->begin();
3392           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3393             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3394         }
3395     }
3396   else//meshdimension==1
3397     {
3398       double tmp[2];
3399       for(int i=0;i<nbOfCells;i++)
3400         {
3401           int offset=connI[i];
3402           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3403           double n=INTERP_KERNEL::norm<2>(tmp);
3404           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3405           *vals++=-tmp[1];
3406           *vals++=tmp[0];
3407         }
3408     }
3409   ret->setArray(array);
3410   ret->setMesh(this);
3411   ret->synchronizeTimeWithSupport();
3412   return ret.retn();
3413 }
3414
3415 /*!
3416  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3417  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3418  * and are normalized.
3419  * <br> \a this can be either 
3420  * - a  2D mesh in 2D or 3D space or 
3421  * - an 1D mesh in 2D space.
3422  * 
3423  * This method avoids building explicitly a part of \a this mesh to perform the work.
3424  *  \param [in] begin - an array of cell ids of interest.
3425  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3426  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3427  *          cells and one time. The caller is to delete this field using decrRef() as
3428  *          it is no more needed.
3429  *  \throw If the nodal connectivity of cells is not defined.
3430  *  \throw If the coordinates array is not set.
3431  *  \throw If the mesh dimension is not set.
3432  *  \throw If the mesh and space dimension is not as specified above.
3433  *  \sa buildOrthogonalField()
3434  *
3435  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3436  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3437  */
3438 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3439 {
3440   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3441     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3442   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3443   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3444   std::size_t nbelems=std::distance(begin,end);
3445   int nbComp=getMeshDimension()+1;
3446   array->alloc((int)nbelems,nbComp);
3447   double *vals=array->getPointer();
3448   const int *connI=_nodal_connec_index->getConstPointer();
3449   const int *conn=_nodal_connec->getConstPointer();
3450   const double *coords=_coords->getConstPointer();
3451   if(getMeshDimension()==2)
3452     {
3453       if(getSpaceDimension()==3)
3454         {
3455           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3456           const double *locPtr=loc->getConstPointer();
3457           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3458             {
3459               int offset=connI[*i];
3460               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3461               double n=INTERP_KERNEL::norm<3>(vals);
3462               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3463             }
3464         }
3465       else
3466         {
3467           for(std::size_t i=0;i<nbelems;i++)
3468             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3469         }
3470     }
3471   else//meshdimension==1
3472     {
3473       double tmp[2];
3474       for(const int *i=begin;i!=end;i++)
3475         {
3476           int offset=connI[*i];
3477           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3478           double n=INTERP_KERNEL::norm<2>(tmp);
3479           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3480           *vals++=-tmp[1];
3481           *vals++=tmp[0];
3482         }
3483     }
3484   ret->setArray(array);
3485   ret->setMesh(this);
3486   ret->synchronizeTimeWithSupport();
3487   return ret.retn();
3488 }
3489
3490 /*!
3491  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3492  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3493  * and are \b not normalized.
3494  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3495  *          cells and one time. The caller is to delete this field using decrRef() as
3496  *          it is no more needed.
3497  *  \throw If the nodal connectivity of cells is not defined.
3498  *  \throw If the coordinates array is not set.
3499  *  \throw If \a this->getMeshDimension() != 1.
3500  *  \throw If \a this mesh includes cells of type other than SEG2.
3501  */
3502 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3503 {
3504    if(getMeshDimension()!=1)
3505     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3506    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3507      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3508    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3509    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3510    int nbOfCells=getNumberOfCells();
3511    int spaceDim=getSpaceDimension();
3512    array->alloc(nbOfCells,spaceDim);
3513    double *pt=array->getPointer();
3514    const double *coo=getCoords()->getConstPointer();
3515    std::vector<int> conn;
3516    conn.reserve(2);
3517    for(int i=0;i<nbOfCells;i++)
3518      {
3519        conn.resize(0);
3520        getNodeIdsOfCell(i,conn);
3521        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3522      }
3523    ret->setArray(array);
3524    ret->setMesh(this);
3525    ret->synchronizeTimeWithSupport();
3526    return ret.retn();   
3527 }
3528
3529 /*!
3530  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3531  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3532  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3533  * from. If a result face is shared by two 3D cells, then the face in included twice in
3534  * the result mesh.
3535  *  \param [in] origin - 3 components of a point defining location of the plane.
3536  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3537  *         must be greater than 1e-6.
3538  *  \param [in] eps - half-thickness of the plane.
3539  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3540  *         producing correspondent 2D cells. The caller is to delete this array
3541  *         using decrRef() as it is no more needed.
3542  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3543  *         not share the node coordinates array with \a this mesh. The caller is to
3544  *         delete this mesh using decrRef() as it is no more needed.  
3545  *  \throw If the coordinates array is not set.
3546  *  \throw If the nodal connectivity of cells is not defined.
3547  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3548  *  \throw If magnitude of \a vec is less than 1e-6.
3549  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3550  *  \throw If \a this includes quadratic cells.
3551  */
3552 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3553 {
3554   checkFullyDefined();
3555   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3556     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3557   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3558   if(candidates->empty())
3559     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3560   std::vector<int> nodes;
3561   DataArrayInt *cellIds1D=0;
3562   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3563   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3564   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3565   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3566   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3567   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3568   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3569   revDesc2=0; revDescIndx2=0;
3570   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3571   revDesc1=0; revDescIndx1=0;
3572   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3573   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3574   //
3575   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3576   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3577     cut3DCurve[*it]=-1;
3578   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3579   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3580   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3581                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3582                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3583   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3584   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3585   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3586   if(cellIds2->empty())
3587     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3588   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3589   ret->setCoords(mDesc1->getCoords());
3590   ret->setConnectivity(conn,connI,true);
3591   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3592   return ret.retn();
3593 }
3594
3595 /*!
3596  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3597 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
3598 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3599 the result mesh.
3600  *  \param [in] origin - 3 components of a point defining location of the plane.
3601  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3602  *         must be greater than 1e-6.
3603  *  \param [in] eps - half-thickness of the plane.
3604  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3605  *         producing correspondent segments. The caller is to delete this array
3606  *         using decrRef() as it is no more needed.
3607  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3608  *         mesh in 3D space. This mesh does not share the node coordinates array with
3609  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3610  *         no more needed. 
3611  *  \throw If the coordinates array is not set.
3612  *  \throw If the nodal connectivity of cells is not defined.
3613  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3614  *  \throw If magnitude of \a vec is less than 1e-6.
3615  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3616  *  \throw If \a this includes quadratic cells.
3617  */
3618 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3619 {
3620   checkFullyDefined();
3621   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3622     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3623   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3624   if(candidates->empty())
3625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3626   std::vector<int> nodes;
3627   DataArrayInt *cellIds1D=0;
3628   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3629   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3630   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3632   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3633   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3634   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3635   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3637   //
3638   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3639   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3640     cut3DCurve[*it]=-1;
3641   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3642   int ncellsSub=subMesh->getNumberOfCells();
3643   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3644   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3645                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3646                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3648   conn->alloc(0,1);
3649   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3650   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3651   for(int i=0;i<ncellsSub;i++)
3652     {
3653       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3654         {
3655           if(cut3DSurf[i].first!=-2)
3656             {
3657               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3658               connI->pushBackSilent(conn->getNumberOfTuples());
3659               cellIds2->pushBackSilent(i);
3660             }
3661           else
3662             {
3663               int cellId3DSurf=cut3DSurf[i].second;
3664               int offset=nodalI[cellId3DSurf]+1;
3665               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3666               for(int j=0;j<nbOfEdges;j++)
3667                 {
3668                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3669                   connI->pushBackSilent(conn->getNumberOfTuples());
3670                   cellIds2->pushBackSilent(cellId3DSurf);
3671                 }
3672             }
3673         }
3674     }
3675   if(cellIds2->empty())
3676     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3677   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3678   ret->setCoords(mDesc1->getCoords());
3679   ret->setConnectivity(conn,connI,true);
3680   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3681   return ret.retn();
3682 }
3683
3684 /*!
3685  * Finds cells whose bounding boxes intersect a given plane.
3686  *  \param [in] origin - 3 components of a point defining location of the plane.
3687  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3688  *         must be greater than 1e-6.
3689  *  \param [in] eps - half-thickness of the plane.
3690  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3691  *         cells. The caller is to delete this array using decrRef() as it is no more
3692  *         needed.
3693  *  \throw If the coordinates array is not set.
3694  *  \throw If the nodal connectivity of cells is not defined.
3695  *  \throw If \a this->getSpaceDimension() != 3.
3696  *  \throw If magnitude of \a vec is less than 1e-6.
3697  *  \sa buildSlice3D()
3698  */
3699 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3700 {
3701   checkFullyDefined();
3702   if(getSpaceDimension()!=3)
3703     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3704   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3705   if(normm<1e-6)
3706     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3707   double vec2[3];
3708   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3709   double angle=acos(vec[2]/normm);
3710   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3711   double bbox[6];
3712   if(angle>eps)
3713     {
3714       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3715       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3716       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3717       mw->setCoords(coo);
3718       mw->getBoundingBox(bbox);
3719       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3720       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3721     }
3722   else
3723     {
3724       getBoundingBox(bbox);
3725       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3726       cellIds=getCellsInBoundingBox(bbox,eps);
3727     }
3728   return cellIds.retn();
3729 }
3730
3731 /*!
3732  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3733  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3734  * No consideration of coordinate is done by this method.
3735  * 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)
3736  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3737  */
3738 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3739 {
3740   if(getMeshDimension()!=1)
3741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3742   int nbCells=getNumberOfCells();
3743   if(nbCells<1)
3744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3745   const int *connI=_nodal_connec_index->getConstPointer();
3746   const int *conn=_nodal_connec->getConstPointer();
3747   int ref=conn[connI[0]+2];
3748   for(int i=1;i<nbCells;i++)
3749     {
3750       if(conn[connI[i]+1]!=ref)
3751         return false;
3752       ref=conn[connI[i]+2];
3753     }
3754   return true;
3755 }
3756
3757 /*!
3758  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3759  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3760  * \param pt reference point of the line
3761  * \param v normalized director vector of the line
3762  * \param eps max precision before throwing an exception
3763  * \param res output of size this->getNumberOfCells
3764  */
3765 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3766 {
3767   if(getMeshDimension()!=1)
3768     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3769    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3770      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3771    if(getSpaceDimension()!=3)
3772      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3773    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3774    const double *fPtr=f->getArray()->getConstPointer();
3775    double tmp[3];
3776    for(int i=0;i<getNumberOfCells();i++)
3777      {
3778        const double *tmp1=fPtr+3*i;
3779        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3780        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3781        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3782        double n1=INTERP_KERNEL::norm<3>(tmp);
3783        n1/=INTERP_KERNEL::norm<3>(tmp1);
3784        if(n1>eps)
3785          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3786      }
3787    const double *coo=getCoords()->getConstPointer();
3788    for(int i=0;i<getNumberOfNodes();i++)
3789      {
3790        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3791        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3792        res[i]=std::accumulate(tmp,tmp+3,0.);
3793      }
3794 }
3795
3796 /*!
3797  * 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. 
3798  * \a this is expected to be a mesh so that its space dimension is equal to its
3799  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3800  * 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).
3801  
3802  * 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
3803  * 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).
3804  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3805  *
3806  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3807  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3808  *
3809  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3810  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3811  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3812  * \return the positive value of the distance.
3813  * \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
3814  * dimension - 1.
3815  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3816  */
3817 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3818 {
3819   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3820   if(meshDim!=spaceDim-1)
3821     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3822   if(meshDim!=2 && meshDim!=1)
3823     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3824   checkFullyDefined();
3825   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3826     { 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()); }
3827   DataArrayInt *ret1=0;
3828   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3829   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3831   cellId=*ret1Safe->begin();
3832   return *ret0->begin();
3833 }
3834
3835 /*!
3836  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3837  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3838  * 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
3839  * 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).
3840  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3841  * 
3842  * \a this is expected to be a mesh so that its space dimension is equal to its
3843  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3844  * 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).
3845  *
3846  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3847  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3848  *
3849  * \param [in] pts the list of points in which each tuple represents a point
3850  * \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.
3851  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3852  * \throw if number of components of \a pts is not equal to the space dimension.
3853  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3854  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3855  */
3856 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3857 {
3858   if(!pts)
3859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3860   pts->checkAllocated();
3861   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3862   if(meshDim!=spaceDim-1)
3863     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3864   if(meshDim!=2 && meshDim!=1)
3865     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3866   if(pts->getNumberOfComponents()!=spaceDim)
3867     {
3868       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3869       throw INTERP_KERNEL::Exception(oss.str().c_str());
3870     }
3871   checkFullyDefined();
3872   int nbCells=getNumberOfCells();
3873   if(nbCells==0)
3874     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3875   int nbOfPts=pts->getNumberOfTuples();
3876   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3878   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3879   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3880   std::vector<double> bbox;
3881   getBoundingBoxForBBTree(bbox);
3882   switch(spaceDim)
3883     {
3884     case 3:
3885       {
3886         BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3887         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3888           {
3889             double x=std::numeric_limits<double>::max();
3890             std::vector<int> elems;
3891             myTree.getMinDistanceOfMax(ptsPtr,x);
3892             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3893             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3894           }
3895         break;
3896       }
3897     case 2:
3898       {
3899         BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3900         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3901           {
3902             double x=std::numeric_limits<double>::max();
3903             std::vector<int> elems;
3904             myTree.getMinDistanceOfMax(ptsPtr,x);
3905             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3906             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3907           }
3908         break;
3909       }
3910     default:
3911       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3912     }
3913   cellIds=ret1.retn();
3914   return ret0.retn();
3915 }
3916
3917 /*!
3918  * \param [in] pt the start pointer (included) of the coordinates of the point
3919  * \param [in] cellIdsBg the start pointer (included) of cellIds
3920  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3921  * \param [in] nc nodal connectivity
3922  * \param [in] ncI nodal connectivity index
3923  * \param [in,out] ret0 the min distance between \a this and the external input point
3924  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3925  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3926  */
3927 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)
3928 {
3929   cellId=-1;
3930   ret0=std::numeric_limits<double>::max();
3931   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3932     {
3933       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3934         {
3935         case INTERP_KERNEL::NORM_TRI3:
3936           {
3937             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3938             if(tmp<ret0)
3939               { ret0=tmp; cellId=*zeCell; }
3940             break;
3941           }
3942         case INTERP_KERNEL::NORM_QUAD4:
3943         case INTERP_KERNEL::NORM_POLYGON:
3944           {
3945             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3946             if(tmp<ret0)
3947               { ret0=tmp; cellId=*zeCell; }
3948             break;
3949           }
3950         default:
3951           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3952         }
3953     }
3954 }
3955
3956 /*!
3957  * \param [in] pt the start pointer (included) of the coordinates of the point
3958  * \param [in] cellIdsBg the start pointer (included) of cellIds
3959  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3960  * \param [in] nc nodal connectivity
3961  * \param [in] ncI nodal connectivity index
3962  * \param [in,out] ret0 the min distance between \a this and the external input point
3963  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3964  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3965  */
3966 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)
3967 {
3968   cellId=-1;
3969   ret0=std::numeric_limits<double>::max();
3970   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3971     {
3972        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3973         {
3974         case INTERP_KERNEL::NORM_SEG2:
3975           {
3976             std::size_t uselessEntry=0;
3977             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3978             tmp=sqrt(tmp);
3979             if(tmp<ret0)
3980               { ret0=tmp; cellId=*zeCell; }
3981             break;
3982           }
3983         default:
3984           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3985         }
3986     }
3987 }
3988
3989 /*!
3990  * Finds cells in contact with a ball (i.e. a point with precision). 
3991  * \warning This method is suitable if the caller intends to evaluate only one
3992  *          point, for more points getCellsContainingPoints() is recommended as it is
3993  *          faster. 
3994  *  \param [in] pos - array of coordinates of the ball central point.
3995  *  \param [in] eps - ball radius.
3996  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
3997  *         if there are no such cells.
3998  *  \throw If the coordinates array is not set.
3999  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4000  */
4001 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4002 {
4003   std::vector<int> elts;
4004   getCellsContainingPoint(pos,eps,elts);
4005   if(elts.empty())
4006     return -1;
4007   return elts.front();
4008 }
4009
4010 /*!
4011  * Finds cells in contact with a ball (i.e. a point with precision).
4012  * \warning This method is suitable if the caller intends to evaluate only one
4013  *          point, for more points getCellsContainingPoints() is recommended as it is
4014  *          faster. 
4015  *  \param [in] pos - array of coordinates of the ball central point.
4016  *  \param [in] eps - ball radius.
4017  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
4018  *         before inserting ids.
4019  *  \throw If the coordinates array is not set.
4020  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4021  *
4022  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4023  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4024  */
4025 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4026 {
4027   std::vector<int> eltsIndex;
4028   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4029 }
4030
4031 /// @cond INTERNAL
4032
4033 namespace ParaMEDMEM
4034 {
4035   template<const int SPACEDIMM>
4036   class DummyClsMCUG
4037   {
4038   public:
4039     static const int MY_SPACEDIM=SPACEDIMM;
4040     static const int MY_MESHDIM=8;
4041     typedef int MyConnType;
4042     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4043     // begin
4044     // useless, but for windows compilation ...
4045     const double* getCoordinatesPtr() const { return 0; }
4046     const int* getConnectivityPtr() const { return 0; }
4047     const int* getConnectivityIndexPtr() const { return 0; }
4048     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4049     // end
4050   };
4051
4052   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4053   {
4054     INTERP_KERNEL::Edge *ret=0;
4055     switch(typ)
4056       {
4057       case INTERP_KERNEL::NORM_SEG2:
4058         {
4059           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4060           break;
4061         }
4062       case INTERP_KERNEL::NORM_SEG3:
4063         {
4064           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4065           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4066           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4067           bool colinearity=inters.areColinears();
4068           delete e1; delete e2;
4069           if(colinearity)
4070             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4071           else
4072             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4073           mapp2[bg[2]].second=false;
4074           break;
4075         }
4076       default:
4077         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4078       }
4079     return ret;
4080   }
4081
4082   /*!
4083    * 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'.
4084    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4085    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4086    */
4087   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4088   {
4089     mapp.clear();
4090     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.
4091     const double *coo=mDesc->getCoords()->getConstPointer();
4092     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4093     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4094     std::set<int> s;
4095     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4096       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4097     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4098       {
4099         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4100         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4101       }
4102     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4103     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4104       {
4105         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4106         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4107       }
4108     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4109       {
4110         if((*it2).second.second)
4111           mapp[(*it2).second.first]=(*it2).first;
4112         ((*it2).second.first)->decrRef();
4113       }
4114     return ret;
4115   }
4116
4117   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4118   {
4119     if(nodeId>=offset2)
4120       {
4121         int locId=nodeId-offset2;
4122         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4123       }
4124     if(nodeId>=offset1)
4125       {
4126         int locId=nodeId-offset1;
4127         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4128       }
4129     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4130   }
4131
4132   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4133                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4134                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4135   {
4136     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4137       {
4138         int eltId1=abs(*desc1)-1;
4139         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4140           {
4141             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4142             if(it==mappRev.end())
4143               {
4144                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4145                 mapp[node]=*it1;
4146                 mappRev[*it1]=node;
4147               }
4148           }
4149       }
4150   }
4151 }
4152
4153 /// @endcond
4154
4155 template<int SPACEDIM>
4156 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4157                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4158 {
4159   std::vector<double> bbox;
4160   eltsIndex.resize(nbOfPoints+1);
4161   eltsIndex[0]=0;
4162   elts.clear();
4163   getBoundingBoxForBBTree(bbox);
4164   int nbOfCells=getNumberOfCells();
4165   const int *conn=_nodal_connec->getConstPointer();
4166   const int *connI=_nodal_connec_index->getConstPointer();
4167   double bb[2*SPACEDIM];
4168   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4169   for(int i=0;i<nbOfPoints;i++)
4170     {
4171       eltsIndex[i+1]=eltsIndex[i];
4172       for(int j=0;j<SPACEDIM;j++)
4173         {
4174           bb[2*j]=pos[SPACEDIM*i+j];
4175           bb[2*j+1]=pos[SPACEDIM*i+j];
4176         }
4177       std::vector<int> candidates;
4178       myTree.getIntersectingElems(bb,candidates);
4179       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4180         {
4181           int sz=connI[(*iter)+1]-connI[*iter]-1;
4182           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4183                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4184                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4185             {
4186               eltsIndex[i+1]++;
4187               elts.push_back(*iter);
4188             }
4189         }
4190     }
4191 }
4192 /*!
4193  * Finds cells in contact with several balls (i.e. points with precision).
4194  * This method is an extension of getCellContainingPoint() and
4195  * getCellsContainingPoint() for the case of multiple points.
4196  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4197  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4198  *         this->getSpaceDimension() * \a nbOfPoints 
4199  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4200  *  \param [in] eps - radius of balls (i.e. the precision).
4201  *  \param [in,out] elts - vector returning ids of found cells.
4202  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4203  *         dividing cell ids in \a elts into groups each referring to one
4204  *         point. Its every element (except the last one) is an index pointing to the
4205  *         first id of a group of cells. For example cells in contact with the *i*-th
4206  *         point are described by following range of indices:
4207  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4208  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4209  *         Number of cells in contact with the *i*-th point is
4210  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4211  *  \throw If the coordinates array is not set.
4212  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4213  *
4214  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4215  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4216  */
4217 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4218                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4219 {
4220   int spaceDim=getSpaceDimension();
4221   int mDim=getMeshDimension();
4222   if(spaceDim==3)
4223     {
4224       if(mDim==3)
4225         {
4226           const double *coords=_coords->getConstPointer();
4227           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4228         }
4229       /*else if(mDim==2)
4230         {
4231           
4232         }*/
4233       else
4234         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4235     }
4236   else if(spaceDim==2)
4237     {
4238       if(mDim==2)
4239         {
4240           const double *coords=_coords->getConstPointer();
4241           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4242         }
4243       else
4244         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4245     }
4246   else if(spaceDim==1)
4247     {
4248       if(mDim==1)
4249         {
4250           const double *coords=_coords->getConstPointer();
4251           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4252         }
4253       else
4254         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4255     }
4256   else
4257     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4258 }
4259
4260 /*!
4261  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4262  * least two its edges intersect each other anywhere except their extremities. An
4263  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4264  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4265  *         cleared before filling in.
4266  *  \param [in] eps - precision.
4267  *  \throw If \a this->getMeshDimension() != 2.
4268  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4269  */
4270 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4271 {
4272   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4273   if(getMeshDimension()!=2)
4274     throw INTERP_KERNEL::Exception(msg);
4275   int spaceDim=getSpaceDimension();
4276   if(spaceDim!=2 && spaceDim!=3)
4277     throw INTERP_KERNEL::Exception(msg);
4278   const int *conn=_nodal_connec->getConstPointer();
4279   const int *connI=_nodal_connec_index->getConstPointer();
4280   int nbOfCells=getNumberOfCells();
4281   std::vector<double> cell2DinS2;
4282   for(int i=0;i<nbOfCells;i++)
4283     {
4284       int offset=connI[i];
4285       int nbOfNodesForCell=connI[i+1]-offset-1;
4286       if(nbOfNodesForCell<=3)
4287         continue;
4288       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4289       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4290       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4291         cells.push_back(i);
4292       cell2DinS2.clear();
4293     }
4294 }
4295
4296 /*!
4297  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4298  *
4299  * 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.
4300  * 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.
4301  * 
4302  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4303  * This convex envelop is computed using Jarvis march algorithm.
4304  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4305  * 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)
4306  * 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.
4307  *
4308  * \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.
4309  */
4310 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4311 {
4312   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4314   checkFullyDefined();
4315   const double *coords=getCoords()->getConstPointer();
4316   int nbOfCells=getNumberOfCells();
4317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4318   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4320   int *workIndexOut=nodalConnecIndexOut->getPointer();
4321   *workIndexOut=0;
4322   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4323   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4324   std::set<INTERP_KERNEL::NormalizedCellType> types;
4325   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4326   isChanged->alloc(0,1);
4327   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4328     {
4329       int pos=nodalConnecOut->getNumberOfTuples();
4330       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4331         isChanged->pushBackSilent(i);
4332       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4333       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4334     }
4335   if(isChanged->empty())
4336     return 0;
4337   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4338   _types=types;
4339   return isChanged.retn();
4340 }
4341
4342 /*!
4343  * This method is \b NOT const because it can modify \a this.
4344  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4345  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4346  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4347  * \b 1 for translation and rotation around point of 'mesh1D'.
4348  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4349  */
4350 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4351 {
4352   checkFullyDefined();
4353   mesh1D->checkFullyDefined();
4354   if(!mesh1D->isContiguous1D())
4355     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4356   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4357     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4358   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4359     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4360   if(mesh1D->getMeshDimension()!=1)
4361     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4362   bool isQuad=false;
4363   if(isPresenceOfQuadratic())
4364     {
4365       if(mesh1D->isFullyQuadratic())
4366         isQuad=true;
4367       else
4368         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4369     }
4370   zipCoords();
4371   int oldNbOfNodes=getNumberOfNodes();
4372   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4373   switch(policy)
4374     {
4375     case 0:
4376       {
4377         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4378         break;
4379       }
4380     case 1:
4381       {
4382         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4383         break;
4384       }
4385     default:
4386       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4387     }
4388   setCoords(newCoords);
4389   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4390   updateTime();
4391   return ret.retn();
4392 }
4393
4394 /*!
4395  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4396  * If it is not the case an exception will be thrown.
4397  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4398  * intersection of plane defined by ('origin','vec').
4399  * This method has one in/out parameter : 'cut3DCurve'.
4400  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4401  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4402  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4403  * This method will throw an exception if \a this contains a non linear segment.
4404  */
4405 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4406 {
4407   checkFullyDefined();
4408   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4409     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4410   int ncells=getNumberOfCells();
4411   int nnodes=getNumberOfNodes();
4412   double vec2[3],vec3[3],vec4[3];
4413   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4414   if(normm<1e-6)
4415     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4416   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4417   const int *conn=_nodal_connec->getConstPointer();
4418   const int *connI=_nodal_connec_index->getConstPointer();
4419   const double *coo=_coords->getConstPointer();
4420   std::vector<double> addCoo;
4421   for(int i=0;i<ncells;i++)
4422     {
4423       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4424         {
4425           if(cut3DCurve[i]==-2)
4426             {
4427               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4428               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];
4429               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4430               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4431               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4432                 {
4433                   const double *st2=coo+3*st;
4434                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4435                   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]));
4436                   if(pos>eps && pos<1-eps)
4437                     {
4438                       int nNode=((int)addCoo.size())/3;
4439                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4440                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4441                       cut3DCurve[i]=nnodes+nNode;
4442                     }
4443                 }
4444             }
4445         }
4446       else
4447         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4448     }
4449   if(!addCoo.empty())
4450     {
4451       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4452       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4453       coo2->alloc(newNbOfNodes,3);
4454       double *tmp=coo2->getPointer();
4455       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4456       std::copy(addCoo.begin(),addCoo.end(),tmp);
4457       DataArrayDouble::SetArrayIn(coo2,_coords);
4458     }
4459 }
4460
4461 /*!
4462  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4463  * \param mesh1D is the input 1D mesh used for translation computation.
4464  * \return newCoords new coords filled by this method. 
4465  */
4466 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4467 {
4468   int oldNbOfNodes=getNumberOfNodes();
4469   int nbOf1DCells=mesh1D->getNumberOfCells();
4470   int spaceDim=getSpaceDimension();
4471   DataArrayDouble *ret=DataArrayDouble::New();
4472   std::vector<bool> isQuads;
4473   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4474   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4475   double *retPtr=ret->getPointer();
4476   const double *coords=getCoords()->getConstPointer();
4477   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4478   std::vector<int> v;
4479   std::vector<double> c;
4480   double vec[3];
4481   v.reserve(3);
4482   c.reserve(6);
4483   for(int i=0;i<nbOf1DCells;i++)
4484     {
4485       v.resize(0);
4486       mesh1D->getNodeIdsOfCell(i,v);
4487       c.resize(0);
4488       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4489       mesh1D->getCoordinatesOfNode(v[0],c);
4490       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4491       for(int j=0;j<oldNbOfNodes;j++)
4492         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4493       if(isQuad)
4494         {
4495           c.resize(0);
4496           mesh1D->getCoordinatesOfNode(v[1],c);
4497           mesh1D->getCoordinatesOfNode(v[0],c);
4498           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4499           for(int j=0;j<oldNbOfNodes;j++)
4500             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4501         }
4502     }
4503   ret->copyStringInfoFrom(*getCoords());
4504   return ret;
4505 }
4506
4507 /*!
4508  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4509  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4510  * \return newCoords new coords filled by this method. 
4511  */
4512 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4513 {
4514   if(mesh1D->getSpaceDimension()==2)
4515     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4516   if(mesh1D->getSpaceDimension()==3)
4517     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4518   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4519 }
4520
4521 /*!
4522  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4523  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4524  * \return newCoords new coords filled by this method. 
4525  */
4526 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4527 {
4528   if(isQuad)
4529     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4530   int oldNbOfNodes=getNumberOfNodes();
4531   int nbOf1DCells=mesh1D->getNumberOfCells();
4532   if(nbOf1DCells<2)
4533     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4534   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4535   int nbOfLevsInVec=nbOf1DCells+1;
4536   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4537   double *retPtr=ret->getPointer();
4538   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4539   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4540   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4541   tmp->setCoords(tmp2);
4542   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4543   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4544   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4545   for(int i=1;i<nbOfLevsInVec;i++)
4546     {
4547       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4548       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4549       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4550       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4551       tmp->translate(vec);
4552       double tmp3[2],radius,alpha,alpha0;
4553       const double *p0=i+1<nbOfLevsInVec?begin:third;
4554       const double *p1=i+1<nbOfLevsInVec?end:begin;
4555       const double *p2=i+1<nbOfLevsInVec?third:end;
4556       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4557       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]);
4558       double angle=acos(cosangle/(radius*radius));
4559       tmp->rotate(end,0,angle);
4560       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4561     }
4562   return ret.retn();
4563 }
4564
4565 /*!
4566  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4567  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4568  * \return newCoords new coords filled by this method. 
4569  */
4570 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4571 {
4572   if(isQuad)
4573     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4574   int oldNbOfNodes=getNumberOfNodes();
4575   int nbOf1DCells=mesh1D->getNumberOfCells();
4576   if(nbOf1DCells<2)
4577     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4578   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4579   int nbOfLevsInVec=nbOf1DCells+1;
4580   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4581   double *retPtr=ret->getPointer();
4582   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4583   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4584   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4585   tmp->setCoords(tmp2);
4586   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4587   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4588   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4589   for(int i=1;i<nbOfLevsInVec;i++)
4590     {
4591       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4592       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4593       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4594       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4595       tmp->translate(vec);
4596       double tmp3[2],radius,alpha,alpha0;
4597       const double *p0=i+1<nbOfLevsInVec?begin:third;
4598       const double *p1=i+1<nbOfLevsInVec?end:begin;
4599       const double *p2=i+1<nbOfLevsInVec?third:end;
4600       double vecPlane[3]={
4601         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4602         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4603         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4604       };
4605       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4606       if(norm>1.e-7)
4607         {
4608           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4609           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4610           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4611           double s2=norm2;
4612           double c2=cos(asin(s2));
4613           double m[3][3]={
4614             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4615             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4616             {-vec2[1]*s2, vec2[0]*s2, c2}
4617           };
4618           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]};
4619           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]};
4620           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]};
4621           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4622           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]);
4623           double angle=acos(cosangle/(radius*radius));
4624           tmp->rotate(end,vecPlane,angle);
4625           
4626         }
4627       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4628     }
4629   return ret.retn();
4630 }
4631
4632 /*!
4633  * This method is private because not easy to use for end user. This method is const contrary to
4634  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4635  * the coords sorted slice by slice.
4636  * \param isQuad specifies presence of quadratic cells.
4637  */
4638 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4639 {
4640   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4641   int nbOf2DCells=getNumberOfCells();
4642   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4643   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4644   const int *conn=_nodal_connec->getConstPointer();
4645   const int *connI=_nodal_connec_index->getConstPointer();
4646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4648   newConnI->alloc(nbOf3DCells+1,1);
4649   int *newConnIPtr=newConnI->getPointer();
4650   *newConnIPtr++=0;
4651   std::vector<int> newc;
4652   for(int j=0;j<nbOf2DCells;j++)
4653     {
4654       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4655       *newConnIPtr++=(int)newc.size();
4656     }
4657   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4658   int *newConnPtr=newConn->getPointer();
4659   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4660   newConnIPtr=newConnI->getPointer();
4661   for(int iz=0;iz<nbOf1DCells;iz++)
4662     {
4663       if(iz!=0)
4664         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4665       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4666         {
4667           int icell=(int)(iter-newc.begin());
4668           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4669             {
4670               if(*iter!=-1)
4671                 *newConnPtr=(*iter)+iz*deltaPerLev;
4672               else
4673                 *newConnPtr=-1;
4674             }
4675           else
4676             *newConnPtr=(*iter);
4677         }
4678     }
4679   ret->setConnectivity(newConn,newConnI,true);
4680   ret->setCoords(getCoords());
4681   return ret;
4682 }
4683
4684 /*!
4685  * Checks if \a this mesh is constituted by only quadratic cells.
4686  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4687  *  \throw If the coordinates array is not set.
4688  *  \throw If the nodal connectivity of cells is not defined.
4689  */
4690 bool MEDCouplingUMesh::isFullyQuadratic() const
4691 {
4692   checkFullyDefined();
4693   bool ret=true;
4694   int nbOfCells=getNumberOfCells();
4695   for(int i=0;i<nbOfCells && ret;i++)
4696     {
4697       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4698       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4699       ret=cm.isQuadratic();
4700     }
4701   return ret;
4702 }
4703
4704 /*!
4705  * Checks if \a this mesh includes any quadratic cell.
4706  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4707  *  \throw If the coordinates array is not set.
4708  *  \throw If the nodal connectivity of cells is not defined.
4709  */
4710 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4711 {
4712   checkFullyDefined();
4713   bool ret=false;
4714   int nbOfCells=getNumberOfCells();
4715   for(int i=0;i<nbOfCells && !ret;i++)
4716     {
4717       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4718       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4719       ret=cm.isQuadratic();
4720     }
4721   return ret;
4722 }
4723
4724 /*!
4725  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4726  * this mesh, it remains unchanged.
4727  *  \throw If the coordinates array is not set.
4728  *  \throw If the nodal connectivity of cells is not defined.
4729  */
4730 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4731 {
4732   checkFullyDefined();
4733   int nbOfCells=getNumberOfCells();
4734   int delta=0;
4735   const int *iciptr=_nodal_connec_index->getConstPointer();
4736   for(int i=0;i<nbOfCells;i++)
4737     {
4738       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4739       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4740       if(cm.isQuadratic())
4741         {
4742           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4743           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4744           if(!cml.isDynamic())
4745             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4746           else
4747             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4748         }
4749     }
4750   if(delta==0)
4751     return ;
4752   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4754   const int *icptr=_nodal_connec->getConstPointer();
4755   newConn->alloc(getMeshLength()-delta,1);
4756   newConnI->alloc(nbOfCells+1,1);
4757   int *ocptr=newConn->getPointer();
4758   int *ociptr=newConnI->getPointer();
4759   *ociptr=0;
4760   _types.clear();
4761   for(int i=0;i<nbOfCells;i++,ociptr++)
4762     {
4763       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4764       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4765       if(!cm.isQuadratic())
4766         {
4767           _types.insert(type);
4768           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4769           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4770         }
4771       else
4772         {
4773           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4774           _types.insert(typel);
4775           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4776           int newNbOfNodes=cml.getNumberOfNodes();
4777           if(cml.isDynamic())
4778             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4779           *ocptr++=(int)typel;
4780           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4781           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4782         }
4783     }
4784   setConnectivity(newConn,newConnI,false);
4785 }
4786
4787 /*!
4788  * This method converts all linear cell in \a this to quadratic one.
4789  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4790  * 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)
4791  * 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.
4792  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4793  * end of the existing coordinates.
4794  * 
4795  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4796  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4797  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4798  * 
4799  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4800  *
4801  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4802  */
4803 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4804 {
4805   DataArrayInt *conn=0,*connI=0;
4806   DataArrayDouble *coords=0;
4807   std::set<INTERP_KERNEL::NormalizedCellType> types;
4808   checkFullyDefined();
4809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4810   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4811   int meshDim=getMeshDimension();
4812   switch(conversionType)
4813     {
4814     case 0:
4815       switch(meshDim)
4816         {
4817         case 1:
4818           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4819           connSafe=conn; connISafe=connI; coordsSafe=coords;
4820           break;
4821         case 2:
4822           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4823           connSafe=conn; connISafe=connI; coordsSafe=coords;
4824           break;
4825         case 3:
4826           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4827           connSafe=conn; connISafe=connI; coordsSafe=coords;
4828           break;
4829         default:
4830           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4831         }
4832       break;
4833     case 1:
4834       {
4835         switch(meshDim)
4836         {
4837         case 1:
4838           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4839           connSafe=conn; connISafe=connI; coordsSafe=coords;
4840           break;
4841         case 2:
4842           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4843           connSafe=conn; connISafe=connI; coordsSafe=coords;
4844           break;
4845         case 3:
4846           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4847           connSafe=conn; connISafe=connI; coordsSafe=coords;
4848           break;
4849         default:
4850           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4851         }
4852         break;
4853       }
4854     default:
4855       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4856     }
4857   setConnectivity(connSafe,connISafe,false);
4858   _types=types;
4859   setCoords(coordsSafe);
4860   return ret.retn();
4861 }
4862
4863 /*!
4864  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4865  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4866  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4867  */
4868 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4869 {
4870   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4871   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4872   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4873   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4874   int nbOfCells=getNumberOfCells();
4875   int nbOfNodes=getNumberOfNodes();
4876   const int *cPtr=_nodal_connec->getConstPointer();
4877   const int *icPtr=_nodal_connec_index->getConstPointer();
4878   int lastVal=0,offset=nbOfNodes;
4879   for(int i=0;i<nbOfCells;i++,icPtr++)
4880     {
4881       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4882       if(type==INTERP_KERNEL::NORM_SEG2)
4883         {
4884           types.insert(INTERP_KERNEL::NORM_SEG3);
4885           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4886           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4887           newConn->pushBackSilent(offset++);
4888           lastVal+=4;
4889           newConnI->pushBackSilent(lastVal);
4890           ret->pushBackSilent(i);
4891         }
4892       else
4893         {
4894           types.insert(type);
4895           lastVal+=(icPtr[1]-icPtr[0]);
4896           newConnI->pushBackSilent(lastVal);
4897           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4898         }
4899     }
4900   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4901   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4902   return ret.retn();
4903 }
4904
4905 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)
4906 {
4907   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4908   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4909   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4910   //
4911   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4912   DataArrayInt *conn1D=0,*conn1DI=0;
4913   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4914   DataArrayDouble *coordsTmp=0;
4915   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4916   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4917   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4918   const int *c1DPtr=conn1D->begin();
4919   const int *c1DIPtr=conn1DI->begin();
4920   int nbOfCells=getNumberOfCells();
4921   const int *cPtr=_nodal_connec->getConstPointer();
4922   const int *icPtr=_nodal_connec_index->getConstPointer();
4923   int lastVal=0;
4924   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4925     {
4926       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4927       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4928       if(!cm.isQuadratic())
4929         {
4930           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4931           types.insert(typ2); newConn->pushBackSilent(typ2);
4932           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4933           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4934             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4935           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4936           newConnI->pushBackSilent(lastVal);
4937           ret->pushBackSilent(i);
4938         }
4939       else
4940         {
4941           types.insert(typ);
4942           lastVal+=(icPtr[1]-icPtr[0]);
4943           newConnI->pushBackSilent(lastVal);
4944           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4945         }
4946     }
4947   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4948   return ret.retn();
4949 }
4950
4951 /*!
4952  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4953  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4954  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4955  */
4956 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4957 {
4958   
4959   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4960   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4961   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4962 }
4963
4964 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4965 {
4966   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4967   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4968   //
4969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4971   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4972   //
4973   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4974   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4975   DataArrayInt *conn1D=0,*conn1DI=0;
4976   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4977   DataArrayDouble *coordsTmp=0;
4978   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4979   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4980   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4981   const int *c1DPtr=conn1D->begin();
4982   const int *c1DIPtr=conn1DI->begin();
4983   int nbOfCells=getNumberOfCells();
4984   const int *cPtr=_nodal_connec->getConstPointer();
4985   const int *icPtr=_nodal_connec_index->getConstPointer();
4986   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4987   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4988     {
4989       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4990       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4991       if(!cm.isQuadratic())
4992         {
4993           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4994           types.insert(typ2); newConn->pushBackSilent(typ2);
4995           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4996           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4997             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4998           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4999           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5000           newConnI->pushBackSilent(lastVal);
5001           ret->pushBackSilent(i);
5002         }
5003       else
5004         {
5005           types.insert(typ);
5006           lastVal+=(icPtr[1]-icPtr[0]);
5007           newConnI->pushBackSilent(lastVal);
5008           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5009         }
5010     }
5011   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5012   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5013   return ret.retn();
5014 }
5015
5016 /*!
5017  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5018  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5019  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5020  */
5021 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5022 {
5023   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5024   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5025   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5026 }
5027
5028 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5029 {
5030   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5031   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5032   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5033   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5034   //
5035   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5036   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5037   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5038   //
5039   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5040   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5041   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5042   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5043   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5044   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5045   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5046   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5047   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5048   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5049   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5050   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5051   int nbOfCells=getNumberOfCells();
5052   const int *cPtr=_nodal_connec->getConstPointer();
5053   const int *icPtr=_nodal_connec_index->getConstPointer();
5054   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5055   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5056     {
5057       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5058       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5059       if(!cm.isQuadratic())
5060         {
5061           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5062           if(typ2==INTERP_KERNEL::NORM_ERROR)
5063             {
5064               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5065               throw INTERP_KERNEL::Exception(oss.str().c_str());
5066             }
5067           types.insert(typ2); newConn->pushBackSilent(typ2);
5068           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5069           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5070             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5071           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5072             {
5073               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5074               int tmpPos=newConn->getNumberOfTuples();
5075               newConn->pushBackSilent(nodeId2);
5076               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5077             }
5078           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5079           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5080           newConnI->pushBackSilent(lastVal);
5081           ret->pushBackSilent(i);
5082         }
5083       else
5084         {
5085           types.insert(typ);
5086           lastVal+=(icPtr[1]-icPtr[0]);
5087           newConnI->pushBackSilent(lastVal);
5088           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5089         }
5090     }
5091   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5092   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5093   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5094   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5095   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5096   int *c=newConn->getPointer();
5097   const int *cI(newConnI->begin());
5098   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5099     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5100   offset=coordsTmp2Safe->getNumberOfTuples();
5101   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5102     c[cI[(*elt)+1]-1]+=offset;
5103   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5104   return ret.retn();
5105 }
5106
5107 /*!
5108  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5109  * so that the number of cells remains the same. Quadratic faces are converted to
5110  * polygons. This method works only for 2D meshes in
5111  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5112  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5113  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5114  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5115  *         a polylinized edge constituting the input polygon.
5116  *  \throw If the coordinates array is not set.
5117  *  \throw If the nodal connectivity of cells is not defined.
5118  *  \throw If \a this->getMeshDimension() != 2.
5119  *  \throw If \a this->getSpaceDimension() != 2.
5120  */
5121 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5122 {
5123   checkFullyDefined();
5124   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5125     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5126   double epsa=fabs(eps);
5127   if(epsa<std::numeric_limits<double>::min())
5128     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 !");
5129   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5131   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5132   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5133   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5134   revDesc1=0; revDescIndx1=0;
5135   mDesc->tessellate2DCurve(eps);
5136   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5137   setCoords(mDesc->getCoords());
5138 }
5139
5140 /*!
5141  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5142  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5143  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5144  *         a sub-divided edge.
5145  *  \throw If the coordinates array is not set.
5146  *  \throw If the nodal connectivity of cells is not defined.
5147  *  \throw If \a this->getMeshDimension() != 1.
5148  *  \throw If \a this->getSpaceDimension() != 2.
5149  */
5150 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5151 {
5152   checkFullyDefined();
5153   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5154     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5155   double epsa=fabs(eps);
5156   if(epsa<std::numeric_limits<double>::min())
5157     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 !");
5158   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5159   int nbCells=getNumberOfCells();
5160   int nbNodes=getNumberOfNodes();
5161   const int *conn=_nodal_connec->getConstPointer();
5162   const int *connI=_nodal_connec_index->getConstPointer();
5163   const double *coords=_coords->getConstPointer();
5164   std::vector<double> addCoo;
5165   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5166   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5167   newConnI->alloc(nbCells+1,1);
5168   int *newConnIPtr=newConnI->getPointer();
5169   *newConnIPtr=0;
5170   int tmp1[3];
5171   INTERP_KERNEL::Node *tmp2[3];
5172   std::set<INTERP_KERNEL::NormalizedCellType> types;
5173   for(int i=0;i<nbCells;i++,newConnIPtr++)
5174     {
5175       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5176       if(cm.isQuadratic())
5177         {//assert(connI[i+1]-connI[i]-1==3)
5178           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5179           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5180           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5181           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5182           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5183           if(eac)
5184             {
5185               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5186               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5187               delete eac;
5188               newConnIPtr[1]=(int)newConn.size();
5189             }
5190           else
5191             {
5192               types.insert(INTERP_KERNEL::NORM_SEG2);
5193               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5194               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5195               newConnIPtr[1]=newConnIPtr[0]+3;
5196             }
5197         }
5198       else
5199         {
5200           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5201           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5202           newConnIPtr[1]=newConnIPtr[0]+3;
5203         }
5204     }
5205   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5206     return ;
5207   _types=types;
5208   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5210   newConnArr->alloc((int)newConn.size(),1);
5211   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5212   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5213   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5214   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5215   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5216   std::copy(addCoo.begin(),addCoo.end(),work);
5217   DataArrayDouble::SetArrayIn(newCoords,_coords);
5218   updateTime();
5219 }
5220
5221 /*!
5222  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5223  * In addition, returns an array mapping new cells to old ones. <br>
5224  * This method typically increases the number of cells in \a this mesh
5225  * but the number of nodes remains \b unchanged.
5226  * That's why the 3D splitting policies
5227  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5228  *  \param [in] policy - specifies a pattern used for splitting.
5229  * The semantic of \a policy is:
5230  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5231  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5232  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5233  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5234  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5235  *          an id of old cell producing it. The caller is to delete this array using
5236  *         decrRef() as it is no more needed. 
5237  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5238  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5239  *          and \a this->getMeshDimension() != 3. 
5240  *  \throw If \a policy is not one of the four discussed above.
5241  *  \throw If the nodal connectivity of cells is not defined.
5242  * \sa MEDCouplingUMesh::tetrahedrize
5243  */
5244 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5245 {
5246   switch(policy)
5247     {
5248     case 0:
5249       return simplexizePol0();
5250     case 1:
5251       return simplexizePol1();
5252     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5253       return simplexizePlanarFace5();
5254     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5255       return simplexizePlanarFace6();
5256     default:
5257       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)");
5258     }
5259 }
5260
5261 /*!
5262  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5263  * - 1D: INTERP_KERNEL::NORM_SEG2
5264  * - 2D: INTERP_KERNEL::NORM_TRI3
5265  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5266  *
5267  * This method is useful for users that need to use P1 field services as
5268  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5269  * All these methods need mesh support containing only simplex cells.
5270  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5271  *  \throw If the coordinates array is not set.
5272  *  \throw If the nodal connectivity of cells is not defined.
5273  *  \throw If \a this->getMeshDimension() < 1.
5274  */
5275 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5276 {
5277   checkFullyDefined();
5278   int mdim=getMeshDimension();
5279   if(mdim<1 || mdim>3)
5280     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5281   int nbCells=getNumberOfCells();
5282   const int *conn=_nodal_connec->getConstPointer();
5283   const int *connI=_nodal_connec_index->getConstPointer();
5284   for(int i=0;i<nbCells;i++)
5285     {
5286       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5287       if(!cm.isSimplex())
5288         return false;
5289     }
5290   return true;
5291 }
5292
5293 /*!
5294  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5295  */
5296 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5297 {
5298   checkConnectivityFullyDefined();
5299   if(getMeshDimension()!=2)
5300     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5301   int nbOfCells=getNumberOfCells();
5302   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5303   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5304   ret->alloc(nbOfCells+nbOfCutCells,1);
5305   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5306   int *retPt=ret->getPointer();
5307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5309   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5310   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5311   int *pt=newConn->getPointer();
5312   int *ptI=newConnI->getPointer();
5313   ptI[0]=0;
5314   const int *oldc=_nodal_connec->getConstPointer();
5315   const int *ci=_nodal_connec_index->getConstPointer();
5316   for(int i=0;i<nbOfCells;i++,ci++)
5317     {
5318       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5319         {
5320           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5321                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5322           pt=std::copy(tmp,tmp+8,pt);
5323           ptI[1]=ptI[0]+4;
5324           ptI[2]=ptI[0]+8;
5325           *retPt++=i;
5326           *retPt++=i;
5327           ptI+=2;
5328         }
5329       else
5330         {
5331           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5332           ptI[1]=ptI[0]+ci[1]-ci[0];
5333           ptI++;
5334           *retPt++=i;
5335         }
5336     }
5337   _nodal_connec->decrRef();
5338   _nodal_connec=newConn.retn();
5339   _nodal_connec_index->decrRef();
5340   _nodal_connec_index=newConnI.retn();
5341   computeTypes();
5342   updateTime();
5343   return ret.retn();
5344 }
5345
5346 /*!
5347  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5348  */
5349 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5350 {
5351   checkConnectivityFullyDefined();
5352   if(getMeshDimension()!=2)
5353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5354   int nbOfCells=getNumberOfCells();
5355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5356   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5357   ret->alloc(nbOfCells+nbOfCutCells,1);
5358   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5359   int *retPt=ret->getPointer();
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5362   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5363   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5364   int *pt=newConn->getPointer();
5365   int *ptI=newConnI->getPointer();
5366   ptI[0]=0;
5367   const int *oldc=_nodal_connec->getConstPointer();
5368   const int *ci=_nodal_connec_index->getConstPointer();
5369   for(int i=0;i<nbOfCells;i++,ci++)
5370     {
5371       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5372         {
5373           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5374                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5375           pt=std::copy(tmp,tmp+8,pt);
5376           ptI[1]=ptI[0]+4;
5377           ptI[2]=ptI[0]+8;
5378           *retPt++=i;
5379           *retPt++=i;
5380           ptI+=2;
5381         }
5382       else
5383         {
5384           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5385           ptI[1]=ptI[0]+ci[1]-ci[0];
5386           ptI++;
5387           *retPt++=i;
5388         }
5389     }
5390   _nodal_connec->decrRef();
5391   _nodal_connec=newConn.retn();
5392   _nodal_connec_index->decrRef();
5393   _nodal_connec_index=newConnI.retn();
5394   computeTypes();
5395   updateTime();
5396   return ret.retn();
5397 }
5398
5399 /*!
5400  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5401  */
5402 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5403 {
5404   checkConnectivityFullyDefined();
5405   if(getMeshDimension()!=3)
5406     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5407   int nbOfCells=getNumberOfCells();
5408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5409   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5410   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5411   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5412   int *retPt=ret->getPointer();
5413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5414   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5415   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5416   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5417   int *pt=newConn->getPointer();
5418   int *ptI=newConnI->getPointer();
5419   ptI[0]=0;
5420   const int *oldc=_nodal_connec->getConstPointer();
5421   const int *ci=_nodal_connec_index->getConstPointer();
5422   for(int i=0;i<nbOfCells;i++,ci++)
5423     {
5424       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5425         {
5426           for(int j=0;j<5;j++,pt+=5,ptI++)
5427             {
5428               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5429               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];
5430               *retPt++=i;
5431               ptI[1]=ptI[0]+5;
5432             }
5433         }
5434       else
5435         {
5436           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5437           ptI[1]=ptI[0]+ci[1]-ci[0];
5438           ptI++;
5439           *retPt++=i;
5440         }
5441     }
5442   _nodal_connec->decrRef();
5443   _nodal_connec=newConn.retn();
5444   _nodal_connec_index->decrRef();
5445   _nodal_connec_index=newConnI.retn();
5446   computeTypes();
5447   updateTime();
5448   return ret.retn();
5449 }
5450
5451 /*!
5452  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5453  */
5454 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5455 {
5456   checkConnectivityFullyDefined();
5457   if(getMeshDimension()!=3)
5458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5459   int nbOfCells=getNumberOfCells();
5460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5461   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5462   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5463   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5464   int *retPt=ret->getPointer();
5465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5467   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5468   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5469   int *pt=newConn->getPointer();
5470   int *ptI=newConnI->getPointer();
5471   ptI[0]=0;
5472   const int *oldc=_nodal_connec->getConstPointer();
5473   const int *ci=_nodal_connec_index->getConstPointer();
5474   for(int i=0;i<nbOfCells;i++,ci++)
5475     {
5476       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5477         {
5478           for(int j=0;j<6;j++,pt+=5,ptI++)
5479             {
5480               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5481               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];
5482               *retPt++=i;
5483               ptI[1]=ptI[0]+5;
5484             }
5485         }
5486       else
5487         {
5488           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5489           ptI[1]=ptI[0]+ci[1]-ci[0];
5490           ptI++;
5491           *retPt++=i;
5492         }
5493     }
5494   _nodal_connec->decrRef();
5495   _nodal_connec=newConn.retn();
5496   _nodal_connec_index->decrRef();
5497   _nodal_connec_index=newConnI.retn();
5498   computeTypes();
5499   updateTime();
5500   return ret.retn();
5501 }
5502
5503 /*!
5504  * 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.
5505  * This method completly ignore coordinates.
5506  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5507  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5508  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5509  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5510  */
5511 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5512 {
5513   checkFullyDefined();
5514   if(getMeshDimension()!=2)
5515     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5516   int nbOfCells=getNumberOfCells();
5517   int *connI=_nodal_connec_index->getPointer();
5518   int newConnLgth=0;
5519   for(int i=0;i<nbOfCells;i++,connI++)
5520     {
5521       int offset=descIndex[i];
5522       int nbOfEdges=descIndex[i+1]-offset;
5523       //
5524       bool ddirect=desc[offset+nbOfEdges-1]>0;
5525       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5526       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5527       for(int j=0;j<nbOfEdges;j++)
5528         {
5529           bool direct=desc[offset+j]>0;
5530           int edgeId=std::abs(desc[offset+j])-1;
5531           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5532             {
5533               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5534               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5535               int ref2=direct?id1:id2;
5536               if(ref==ref2)
5537                 {
5538                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5539                   newConnLgth+=nbOfSubNodes-1;
5540                   ref=direct?id2:id1;
5541                 }
5542               else
5543                 {
5544                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5545                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5546                 }
5547             }
5548           else
5549             {
5550               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5551             }
5552         }
5553       newConnLgth++;//+1 is for cell type
5554       connI[1]=newConnLgth;
5555     }
5556   //
5557   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5558   newConn->alloc(newConnLgth,1);
5559   int *work=newConn->getPointer();
5560   for(int i=0;i<nbOfCells;i++)
5561     {
5562       *work++=INTERP_KERNEL::NORM_POLYGON;
5563       int offset=descIndex[i];
5564       int nbOfEdges=descIndex[i+1]-offset;
5565       for(int j=0;j<nbOfEdges;j++)
5566         {
5567           bool direct=desc[offset+j]>0;
5568           int edgeId=std::abs(desc[offset+j])-1;
5569           if(direct)
5570             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5571           else
5572             {
5573               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5574               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5575               work=std::copy(it,it+nbOfSubNodes-1,work);
5576             }
5577         }
5578     }
5579   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5580   _types.clear();
5581   if(nbOfCells>0)
5582     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5583 }
5584
5585 /*!
5586  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5587  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5588  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5589  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5590  * so it can be useful to call mergeNodes() before calling this method.
5591  *  \throw If \a this->getMeshDimension() <= 1.
5592  *  \throw If the coordinates array is not set.
5593  *  \throw If the nodal connectivity of cells is not defined.
5594  */
5595 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5596 {
5597   checkFullyDefined();
5598   if(getMeshDimension()<=1)
5599     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5600   int nbOfCells=getNumberOfCells();
5601   if(nbOfCells<1)
5602     return ;
5603   int initMeshLgth=getMeshLength();
5604   int *conn=_nodal_connec->getPointer();
5605   int *index=_nodal_connec_index->getPointer();
5606   int posOfCurCell=0;
5607   int newPos=0;
5608   int lgthOfCurCell;
5609   for(int i=0;i<nbOfCells;i++)
5610     {
5611       lgthOfCurCell=index[i+1]-posOfCurCell;
5612       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5613       int newLgth;
5614       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5615                                                                                                      conn+newPos+1,newLgth);
5616       conn[newPos]=newType;
5617       newPos+=newLgth+1;
5618       posOfCurCell=index[i+1];
5619       index[i+1]=newPos;
5620     }
5621   if(newPos!=initMeshLgth)
5622     _nodal_connec->reAlloc(newPos);
5623   computeTypes();
5624 }
5625
5626 /*!
5627  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5628  * A cell is considered to be oriented correctly if an angle between its
5629  * normal vector and a given vector is less than \c PI / \c 2.
5630  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5631  *         cells. 
5632  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5633  *         checked.
5634  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5635  *         is not cleared before filling in.
5636  *  \throw If \a this->getMeshDimension() != 2.
5637  *  \throw If \a this->getSpaceDimension() != 3.
5638  *
5639  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5640  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5641  */
5642 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5643 {
5644   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5645     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5646   int nbOfCells=getNumberOfCells();
5647   const int *conn=_nodal_connec->getConstPointer();
5648   const int *connI=_nodal_connec_index->getConstPointer();
5649   const double *coordsPtr=_coords->getConstPointer();
5650   for(int i=0;i<nbOfCells;i++)
5651     {
5652       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5653       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5654         {
5655           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5656           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5657             cells.push_back(i);
5658         }
5659     }
5660 }
5661
5662 /*!
5663  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5664  * considered to be oriented correctly if an angle between its normal vector and a
5665  * given vector is less than \c PI / \c 2. 
5666  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5667  *         cells. 
5668  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5669  *         checked.
5670  *  \throw If \a this->getMeshDimension() != 2.
5671  *  \throw If \a this->getSpaceDimension() != 3.
5672  *
5673  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5674  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5675  */
5676 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5677 {
5678   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5679     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5680   int nbOfCells=getNumberOfCells();
5681   int *conn=_nodal_connec->getPointer();
5682   const int *connI=_nodal_connec_index->getConstPointer();
5683   const double *coordsPtr=_coords->getConstPointer();
5684   bool isModified=false;
5685   for(int i=0;i<nbOfCells;i++)
5686     {
5687       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5688       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5689         {
5690           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5691           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5692             {
5693               isModified=true;
5694               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5695               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5696               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5697             }
5698         }
5699     }
5700   if(isModified)
5701     _nodal_connec->declareAsNew();
5702   updateTime();
5703 }
5704
5705 /*!
5706  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5707  * oriented facets. The normal vector of the facet should point out of the cell.
5708  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5709  *         is not cleared before filling in.
5710  *  \throw If \a this->getMeshDimension() != 3.
5711  *  \throw If \a this->getSpaceDimension() != 3.
5712  *  \throw If the coordinates array is not set.
5713  *  \throw If the nodal connectivity of cells is not defined.
5714  *
5715  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5716  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5717  */
5718 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5719 {
5720   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5721     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5722   int nbOfCells=getNumberOfCells();
5723   const int *conn=_nodal_connec->getConstPointer();
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           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5732             cells.push_back(i);
5733         }
5734     }
5735 }
5736
5737 /*!
5738  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5739  * out of the cell. 
5740  *  \throw If \a this->getMeshDimension() != 3.
5741  *  \throw If \a this->getSpaceDimension() != 3.
5742  *  \throw If the coordinates array is not set.
5743  *  \throw If the nodal connectivity of cells is not defined.
5744  *  \throw If the reparation fails.
5745  *
5746  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5747  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5748  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5749  */
5750 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5751 {
5752   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5753     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5754   int nbOfCells=getNumberOfCells();
5755   int *conn=_nodal_connec->getPointer();
5756   const int *connI=_nodal_connec_index->getConstPointer();
5757   const double *coordsPtr=_coords->getConstPointer();
5758   for(int i=0;i<nbOfCells;i++)
5759     {
5760       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5761       if(type==INTERP_KERNEL::NORM_POLYHED)
5762         {
5763           try
5764             {
5765               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5766                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5767             }
5768           catch(INTERP_KERNEL::Exception& e)
5769             {
5770               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5771               throw INTERP_KERNEL::Exception(oss.str().c_str());
5772             }
5773         }
5774     }
5775   updateTime();
5776 }
5777
5778 /*!
5779  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5780  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5781  * according to which the first facet of the cell should be oriented to have the normal vector
5782  * pointing out of cell.
5783  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5784  *         cells. The caller is to delete this array using decrRef() as it is no more
5785  *         needed. 
5786  *  \throw If \a this->getMeshDimension() != 3.
5787  *  \throw If \a this->getSpaceDimension() != 3.
5788  *  \throw If the coordinates array is not set.
5789  *  \throw If the nodal connectivity of cells is not defined.
5790  *
5791  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5792  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5793  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5794  */
5795 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5796 {
5797   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5798   if(getMeshDimension()!=3)
5799     throw INTERP_KERNEL::Exception(msg);
5800   int spaceDim=getSpaceDimension();
5801   if(spaceDim!=3)
5802     throw INTERP_KERNEL::Exception(msg);
5803   //
5804   int nbOfCells=getNumberOfCells();
5805   int *conn=_nodal_connec->getPointer();
5806   const int *connI=_nodal_connec_index->getConstPointer();
5807   const double *coo=getCoords()->getConstPointer();
5808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5809   for(int i=0;i<nbOfCells;i++)
5810     {
5811       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5812       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5813         {
5814           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5815             {
5816               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5817               cells->pushBackSilent(i);
5818             }
5819         }
5820     }
5821   return cells.retn();
5822 }
5823
5824 /*!
5825  * This method is a faster method to correct orientation of all 3D cells in \a this.
5826  * 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.
5827  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5828  * 
5829  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5830  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5831  */
5832 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5833 {
5834   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5835     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5836   int nbOfCells=getNumberOfCells();
5837   int *conn=_nodal_connec->getPointer();
5838   const int *connI=_nodal_connec_index->getConstPointer();
5839   const double *coordsPtr=_coords->getConstPointer();
5840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5841   for(int i=0;i<nbOfCells;i++)
5842     {
5843       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5844       switch(type)
5845         {
5846         case INTERP_KERNEL::NORM_TETRA4:
5847           {
5848             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5849               {
5850                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5851                 ret->pushBackSilent(i);
5852               }
5853             break;
5854           }
5855         case INTERP_KERNEL::NORM_PYRA5:
5856           {
5857             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5858               {
5859                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5860                 ret->pushBackSilent(i);
5861               }
5862             break;
5863           }
5864         case INTERP_KERNEL::NORM_PENTA6:
5865         case INTERP_KERNEL::NORM_HEXA8:
5866         case INTERP_KERNEL::NORM_HEXGP12:
5867           {
5868             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5869               {
5870                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5871                 ret->pushBackSilent(i);
5872               }
5873             break;
5874           }
5875         case INTERP_KERNEL::NORM_POLYHED:
5876           {
5877             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5878               {
5879                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5880                 ret->pushBackSilent(i);
5881               }
5882             break;
5883           }
5884         default:
5885           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 !");
5886         }
5887     }
5888   updateTime();
5889   return ret.retn();
5890 }
5891
5892 /*!
5893  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5894  * If it is not the case an exception will be thrown.
5895  * This method is fast because the first cell of \a this is used to compute the plane.
5896  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5897  * \param pos output of size at least 3 used to store a point owned of searched plane.
5898  */
5899 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5900 {
5901   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5902     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5903   const int *conn=_nodal_connec->getConstPointer();
5904   const int *connI=_nodal_connec_index->getConstPointer();
5905   const double *coordsPtr=_coords->getConstPointer();
5906   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5907   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5908 }
5909
5910 /*!
5911  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5912  * cells. Currently cells of the following types are treated:
5913  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5914  * For a cell of other type an exception is thrown.
5915  * Space dimension of a 2D mesh can be either 2 or 3.
5916  * The Edge Ratio of a cell \f$t\f$ is: 
5917  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5918  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5919  *  the smallest edge lengths of \f$t\f$.
5920  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5921  *          cells and one time, lying on \a this mesh. The caller is to delete this
5922  *          field using decrRef() as it is no more needed. 
5923  *  \throw If the coordinates array is not set.
5924  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5925  *  \throw If the connectivity data array has more than one component.
5926  *  \throw If the connectivity data array has a named component.
5927  *  \throw If the connectivity index data array has more than one component.
5928  *  \throw If the connectivity index data array has a named component.
5929  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5930  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5931  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5932  */
5933 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5934 {
5935   checkCoherency();
5936   int spaceDim=getSpaceDimension();
5937   int meshDim=getMeshDimension();
5938   if(spaceDim!=2 && spaceDim!=3)
5939     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5940   if(meshDim!=2 && meshDim!=3)
5941     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5942   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5943   ret->setMesh(this);
5944   int nbOfCells=getNumberOfCells();
5945   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5946   arr->alloc(nbOfCells,1);
5947   double *pt=arr->getPointer();
5948   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5949   const int *conn=_nodal_connec->getConstPointer();
5950   const int *connI=_nodal_connec_index->getConstPointer();
5951   const double *coo=_coords->getConstPointer();
5952   double tmp[12];
5953   for(int i=0;i<nbOfCells;i++,pt++)
5954     {
5955       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5956       switch(t)
5957         {
5958           case INTERP_KERNEL::NORM_TRI3:
5959             {
5960               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5961               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5962               break;
5963             }
5964           case INTERP_KERNEL::NORM_QUAD4:
5965             {
5966               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5967               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5968               break;
5969             }
5970           case INTERP_KERNEL::NORM_TETRA4:
5971             {
5972               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5973               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5974               break;
5975             }
5976         default:
5977           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5978         }
5979       conn+=connI[i+1]-connI[i];
5980     }
5981   ret->setName("EdgeRatio");
5982   ret->synchronizeTimeWithSupport();
5983   return ret.retn();
5984 }
5985
5986 /*!
5987  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5988  * cells. Currently cells of the following types are treated:
5989  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5990  * For a cell of other type an exception is thrown.
5991  * Space dimension of a 2D mesh can be either 2 or 3.
5992  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5993  *          cells and one time, lying on \a this mesh. The caller is to delete this
5994  *          field using decrRef() as it is no more needed. 
5995  *  \throw If the coordinates array is not set.
5996  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5997  *  \throw If the connectivity data array has more than one component.
5998  *  \throw If the connectivity data array has a named component.
5999  *  \throw If the connectivity index data array has more than one component.
6000  *  \throw If the connectivity index data array has a named component.
6001  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6002  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6003  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6004  */
6005 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6006 {
6007   checkCoherency();
6008   int spaceDim=getSpaceDimension();
6009   int meshDim=getMeshDimension();
6010   if(spaceDim!=2 && spaceDim!=3)
6011     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6012   if(meshDim!=2 && meshDim!=3)
6013     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6014   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6015   ret->setMesh(this);
6016   int nbOfCells=getNumberOfCells();
6017   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6018   arr->alloc(nbOfCells,1);
6019   double *pt=arr->getPointer();
6020   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6021   const int *conn=_nodal_connec->getConstPointer();
6022   const int *connI=_nodal_connec_index->getConstPointer();
6023   const double *coo=_coords->getConstPointer();
6024   double tmp[12];
6025   for(int i=0;i<nbOfCells;i++,pt++)
6026     {
6027       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6028       switch(t)
6029         {
6030           case INTERP_KERNEL::NORM_TRI3:
6031             {
6032               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6033               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6034               break;
6035             }
6036           case INTERP_KERNEL::NORM_QUAD4:
6037             {
6038               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6039               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6040               break;
6041             }
6042           case INTERP_KERNEL::NORM_TETRA4:
6043             {
6044               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6045               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6046               break;
6047             }
6048         default:
6049           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6050         }
6051       conn+=connI[i+1]-connI[i];
6052     }
6053   ret->setName("AspectRatio");
6054   ret->synchronizeTimeWithSupport();
6055   return ret.retn();
6056 }
6057
6058 /*!
6059  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6060  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6061  * treated: INTERP_KERNEL::NORM_QUAD4.
6062  * For a cell of other type an exception is thrown.
6063  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6064  *          cells and one time, lying on \a this mesh. The caller is to delete this
6065  *          field using decrRef() as it is no more needed. 
6066  *  \throw If the coordinates array is not set.
6067  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6068  *  \throw If the connectivity data array has more than one component.
6069  *  \throw If the connectivity data array has a named component.
6070  *  \throw If the connectivity index data array has more than one component.
6071  *  \throw If the connectivity index data array has a named component.
6072  *  \throw If \a this->getMeshDimension() != 2.
6073  *  \throw If \a this->getSpaceDimension() != 3.
6074  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6075  */
6076 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6077 {
6078   checkCoherency();
6079   int spaceDim=getSpaceDimension();
6080   int meshDim=getMeshDimension();
6081   if(spaceDim!=3)
6082     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6083   if(meshDim!=2)
6084     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6085   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6086   ret->setMesh(this);
6087   int nbOfCells=getNumberOfCells();
6088   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6089   arr->alloc(nbOfCells,1);
6090   double *pt=arr->getPointer();
6091   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6092   const int *conn=_nodal_connec->getConstPointer();
6093   const int *connI=_nodal_connec_index->getConstPointer();
6094   const double *coo=_coords->getConstPointer();
6095   double tmp[12];
6096   for(int i=0;i<nbOfCells;i++,pt++)
6097     {
6098       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6099       switch(t)
6100         {
6101           case INTERP_KERNEL::NORM_QUAD4:
6102             {
6103               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6104               *pt=INTERP_KERNEL::quadWarp(tmp);
6105               break;
6106             }
6107         default:
6108           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6109         }
6110       conn+=connI[i+1]-connI[i];
6111     }
6112   ret->setName("Warp");
6113   ret->synchronizeTimeWithSupport();
6114   return ret.retn();
6115 }
6116
6117
6118 /*!
6119  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6120  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6121  * treated: INTERP_KERNEL::NORM_QUAD4.
6122  * For a cell of other type an exception is thrown.
6123  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6124  *          cells and one time, lying on \a this mesh. The caller is to delete this
6125  *          field using decrRef() as it is no more needed. 
6126  *  \throw If the coordinates array is not set.
6127  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6128  *  \throw If the connectivity data array has more than one component.
6129  *  \throw If the connectivity data array has a named component.
6130  *  \throw If the connectivity index data array has more than one component.
6131  *  \throw If the connectivity index data array has a named component.
6132  *  \throw If \a this->getMeshDimension() != 2.
6133  *  \throw If \a this->getSpaceDimension() != 3.
6134  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6135  */
6136 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6137 {
6138   checkCoherency();
6139   int spaceDim=getSpaceDimension();
6140   int meshDim=getMeshDimension();
6141   if(spaceDim!=3)
6142     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6143   if(meshDim!=2)
6144     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6145   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6146   ret->setMesh(this);
6147   int nbOfCells=getNumberOfCells();
6148   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6149   arr->alloc(nbOfCells,1);
6150   double *pt=arr->getPointer();
6151   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6152   const int *conn=_nodal_connec->getConstPointer();
6153   const int *connI=_nodal_connec_index->getConstPointer();
6154   const double *coo=_coords->getConstPointer();
6155   double tmp[12];
6156   for(int i=0;i<nbOfCells;i++,pt++)
6157     {
6158       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6159       switch(t)
6160         {
6161           case INTERP_KERNEL::NORM_QUAD4:
6162             {
6163               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6164               *pt=INTERP_KERNEL::quadSkew(tmp);
6165               break;
6166             }
6167         default:
6168           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6169         }
6170       conn+=connI[i+1]-connI[i];
6171     }
6172   ret->setName("Skew");
6173   ret->synchronizeTimeWithSupport();
6174   return ret.retn();
6175 }
6176
6177 /*!
6178  * This method aggregate the bbox of each cell and put it into bbox parameter.
6179  * \param bbox out parameter of size 2*spacedim*nbOfcells.
6180  */
6181 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6182 {
6183   int spaceDim=getSpaceDimension();
6184   int nbOfCells=getNumberOfCells();
6185   bbox.resize(2*nbOfCells*spaceDim);
6186   for(int i=0;i<nbOfCells*spaceDim;i++)
6187     {
6188       bbox[2*i]=std::numeric_limits<double>::max();
6189       bbox[2*i+1]=-std::numeric_limits<double>::max();
6190     }
6191   const double *coordsPtr=_coords->getConstPointer();
6192   const int *conn=_nodal_connec->getConstPointer();
6193   const int *connI=_nodal_connec_index->getConstPointer();
6194   for(int i=0;i<nbOfCells;i++)
6195     {
6196       int offset=connI[i]+1;
6197       int nbOfNodesForCell=connI[i+1]-offset;
6198       for(int j=0;j<nbOfNodesForCell;j++)
6199         {
6200           int nodeId=conn[offset+j];
6201           if(nodeId>=0)
6202             for(int k=0;k<spaceDim;k++)
6203               {
6204                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6205                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6206               }
6207         }
6208     }
6209 }
6210
6211 /// @cond INTERNAL
6212
6213 namespace ParaMEDMEMImpl
6214 {
6215   class ConnReader
6216   {
6217   public:
6218     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6219     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6220   private:
6221     const int *_conn;
6222     int _val;
6223   };
6224
6225   class ConnReader2
6226   {
6227   public:
6228     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6229     bool operator() (const int& pos) { return _conn[pos]==_val; }
6230   private:
6231     const int *_conn;
6232     int _val;
6233   };
6234 }
6235
6236 /// @endcond
6237
6238 /*!
6239  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6240  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6241  * \a this is composed in cell types.
6242  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6243  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6244  * This parameter is kept only for compatibility with other methode listed above.
6245  */
6246 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6247 {
6248   checkConnectivityFullyDefined();
6249   const int *conn=_nodal_connec->getConstPointer();
6250   const int *connI=_nodal_connec_index->getConstPointer();
6251   const int *work=connI;
6252   int nbOfCells=getNumberOfCells();
6253   std::size_t n=getAllTypes().size();
6254   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6255   std::set<INTERP_KERNEL::NormalizedCellType> types;
6256   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6257     {
6258       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6259       if(types.find(typ)!=types.end())
6260         {
6261           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6262           oss << " is not contiguous !";
6263           throw INTERP_KERNEL::Exception(oss.str().c_str());
6264         }
6265       types.insert(typ);
6266       ret[3*i]=typ;
6267       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6268       ret[3*i+1]=(int)std::distance(work,work2);
6269       work=work2;
6270     }
6271   return ret;
6272 }
6273
6274 /*!
6275  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6276  * only for types cell, type node is not managed.
6277  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6278  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6279  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6280  * If 2 or more same geometric type is in \a code and exception is thrown too.
6281  *
6282  * This method firstly checks
6283  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6284  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6285  * an exception is thrown too.
6286  * 
6287  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6288  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6289  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6290  */
6291 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6292 {
6293   if(code.empty())
6294     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6295   std::size_t sz=code.size();
6296   std::size_t n=sz/3;
6297   if(sz%3!=0)
6298     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6299   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6300   int nb=0;
6301   bool isNoPflUsed=true;
6302   for(std::size_t i=0;i<n;i++)
6303     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6304       {
6305         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6306         nb+=code[3*i+1];
6307         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6308           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6309         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6310       }
6311   if(types.size()!=n)
6312     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6313   if(isNoPflUsed)
6314     {
6315       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6316         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6317       if(types.size()==_types.size())
6318         return 0;
6319     }
6320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6321   ret->alloc(nb,1);
6322   int *retPtr=ret->getPointer();
6323   const int *connI=_nodal_connec_index->getConstPointer();
6324   const int *conn=_nodal_connec->getConstPointer();
6325   int nbOfCells=getNumberOfCells();
6326   const int *i=connI;
6327   int kk=0;
6328   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6329     {
6330       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6331       int offset=(int)std::distance(connI,i);
6332       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6333       int nbOfCellsOfCurType=(int)std::distance(i,j);
6334       if(code[3*kk+2]==-1)
6335         for(int k=0;k<nbOfCellsOfCurType;k++)
6336           *retPtr++=k+offset;
6337       else
6338         {
6339           int idInIdsPerType=code[3*kk+2];
6340           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6341             {
6342               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6343               if(zePfl)
6344                 {
6345                   zePfl->checkAllocated();
6346                   if(zePfl->getNumberOfComponents()==1)
6347                     {
6348                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6349                         {
6350                           if(*k>=0 && *k<nbOfCellsOfCurType)
6351                             *retPtr=(*k)+offset;
6352                           else
6353                             {
6354                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6355                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6356                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6357                             }
6358                         }
6359                     }
6360                   else
6361                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6362                 }
6363               else
6364                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6365             }
6366           else
6367             {
6368               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6369               oss << " should be in [0," << idsPerType.size() << ") !";
6370               throw INTERP_KERNEL::Exception(oss.str().c_str());
6371             }
6372         }
6373       i=j;
6374     }
6375   return ret.retn();
6376 }
6377
6378 /*!
6379  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6380  * 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.
6381  * 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.
6382  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6383  * 
6384  * \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.
6385  * \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,
6386  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6387  * \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.
6388  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6389  * \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
6390  */
6391 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6392 {
6393   if(!profile)
6394     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6395   if(profile->getNumberOfComponents()!=1)
6396     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6397   checkConnectivityFullyDefined();
6398   const int *conn=_nodal_connec->getConstPointer();
6399   const int *connI=_nodal_connec_index->getConstPointer();
6400   int nbOfCells=getNumberOfCells();
6401   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6402   std::vector<int> typeRangeVals(1);
6403   for(const int *i=connI;i!=connI+nbOfCells;)
6404     {
6405       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6406       if(std::find(types.begin(),types.end(),curType)!=types.end())
6407         {
6408           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6409         }
6410       types.push_back(curType);
6411       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6412       typeRangeVals.push_back((int)std::distance(connI,i));
6413     }
6414   //
6415   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6416   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6417   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6420   //
6421   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6422   code.resize(3*nbOfCastsFinal);
6423   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6424   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6425   for(int i=0;i<nbOfCastsFinal;i++)
6426     {
6427       int castId=castsPresent->getIJ(i,0);
6428       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6429       idsInPflPerType2.push_back(tmp3);
6430       code[3*i]=(int)types[castId];
6431       code[3*i+1]=tmp3->getNumberOfTuples();
6432       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6433       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6434         {
6435           tmp4->copyStringInfoFrom(*profile);
6436           idsPerType2.push_back(tmp4);
6437           code[3*i+2]=(int)idsPerType2.size()-1;
6438         }
6439       else
6440         {
6441           code[3*i+2]=-1;
6442         }
6443     }
6444   std::size_t sz2=idsInPflPerType2.size();
6445   idsInPflPerType.resize(sz2);
6446   for(std::size_t i=0;i<sz2;i++)
6447     {
6448       DataArrayInt *locDa=idsInPflPerType2[i];
6449       locDa->incrRef();
6450       idsInPflPerType[i]=locDa;
6451     }
6452   std::size_t sz=idsPerType2.size();
6453   idsPerType.resize(sz);
6454   for(std::size_t i=0;i<sz;i++)
6455     {
6456       DataArrayInt *locDa=idsPerType2[i];
6457       locDa->incrRef();
6458       idsPerType[i]=locDa;
6459     }
6460 }
6461
6462 /*!
6463  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6464  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6465  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6466  * 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.
6467  */
6468 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6469 {
6470   checkFullyDefined();
6471   nM1LevMesh->checkFullyDefined();
6472   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6473     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6474   if(_coords!=nM1LevMesh->getCoords())
6475     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6476   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6477   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6478   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6479   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6480   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6481   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6482   tmp->setConnectivity(tmp0,tmp1);
6483   tmp->renumberCells(ret0->getConstPointer(),false);
6484   revDesc=tmp->getNodalConnectivity();
6485   revDescIndx=tmp->getNodalConnectivityIndex();
6486   DataArrayInt *ret=0;
6487   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6488     {
6489       int tmp2;
6490       ret->getMaxValue(tmp2);
6491       ret->decrRef();
6492       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6493       throw INTERP_KERNEL::Exception(oss.str().c_str());
6494     }
6495   nM1LevMeshIds=ret;
6496   //
6497   revDesc->incrRef();
6498   revDescIndx->incrRef();
6499   ret1->incrRef();
6500   ret0->incrRef();
6501   meshnM1Old2New=ret0;
6502   return ret1;
6503 }
6504
6505 /*!
6506  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6507  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6508  * in "Old to New" mode.
6509  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6510  *          this array using decrRef() as it is no more needed.
6511  *  \throw If the nodal connectivity of cells is not defined.
6512  */
6513 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6514 {
6515   checkConnectivityFullyDefined();
6516   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6517   renumberCells(ret->getConstPointer(),false);
6518   return ret.retn();
6519 }
6520
6521 /*!
6522  * This methods checks that cells are sorted by their types.
6523  * This method makes asumption (no check) that connectivity is correctly set before calling.
6524  */
6525 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6526 {
6527   checkFullyDefined();
6528   const int *conn=_nodal_connec->getConstPointer();
6529   const int *connI=_nodal_connec_index->getConstPointer();
6530   int nbOfCells=getNumberOfCells();
6531   std::set<INTERP_KERNEL::NormalizedCellType> types;
6532   for(const int *i=connI;i!=connI+nbOfCells;)
6533     {
6534       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6535       if(types.find(curType)!=types.end())
6536         return false;
6537       types.insert(curType);
6538       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6539     }
6540   return true;
6541 }
6542
6543 /*!
6544  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6545  * The geometric type order is specified by MED file.
6546  * 
6547  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6548  */
6549 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6550 {
6551   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6552 }
6553
6554 /*!
6555  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6556  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6557  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6558  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6559  */
6560 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6561 {
6562   checkFullyDefined();
6563   const int *conn=_nodal_connec->getConstPointer();
6564   const int *connI=_nodal_connec_index->getConstPointer();
6565   int nbOfCells=getNumberOfCells();
6566   if(nbOfCells==0)
6567     return true;
6568   int lastPos=-1;
6569   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6570   for(const int *i=connI;i!=connI+nbOfCells;)
6571     {
6572       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6573       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6574       if(isTypeExists!=orderEnd)
6575         {
6576           int pos=(int)std::distance(orderBg,isTypeExists);
6577           if(pos<=lastPos)
6578             return false;
6579           lastPos=pos;
6580           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6581         }
6582       else
6583         {
6584           if(sg.find(curType)==sg.end())
6585             {
6586               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6587               sg.insert(curType);
6588             }
6589           else
6590             return false;
6591         }
6592     }
6593   return true;
6594 }
6595
6596 /*!
6597  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6598  * 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
6599  * 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'.
6600  */
6601 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6602 {
6603   checkConnectivityFullyDefined();
6604   int nbOfCells=getNumberOfCells();
6605   const int *conn=_nodal_connec->getConstPointer();
6606   const int *connI=_nodal_connec_index->getConstPointer();
6607   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6608   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6609   tmpa->alloc(nbOfCells,1);
6610   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6611   tmpb->fillWithZero();
6612   int *tmp=tmpa->getPointer();
6613   int *tmp2=tmpb->getPointer();
6614   for(const int *i=connI;i!=connI+nbOfCells;i++)
6615     {
6616       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6617       if(where!=orderEnd)
6618         {
6619           int pos=(int)std::distance(orderBg,where);
6620           tmp2[pos]++;
6621           tmp[std::distance(connI,i)]=pos;
6622         }
6623       else
6624         {
6625           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6626           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6627           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6628           throw INTERP_KERNEL::Exception(oss.str().c_str());
6629         }
6630     }
6631   nbPerType=tmpb.retn();
6632   return tmpa.retn();
6633 }
6634
6635 /*!
6636  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6637  *
6638  * \return a new object containing the old to new correspondance.
6639  *
6640  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6641  */
6642 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6643 {
6644   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6645 }
6646
6647 /*!
6648  * 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.
6649  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6650  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6651  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6652  */
6653 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6654 {
6655   DataArrayInt *nbPerType=0;
6656   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6657   nbPerType->decrRef();
6658   return tmpa->buildPermArrPerLevel();
6659 }
6660
6661 /*!
6662  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6663  * The number of cells remains unchanged after the call of this method.
6664  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6665  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6666  *
6667  * \return the array giving the correspondance old to new.
6668  */
6669 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6670 {
6671   checkFullyDefined();
6672   computeTypes();
6673   const int *conn=_nodal_connec->getConstPointer();
6674   const int *connI=_nodal_connec_index->getConstPointer();
6675   int nbOfCells=getNumberOfCells();
6676   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6677   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6678     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6679       {
6680         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6681         types.push_back(curType);
6682         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6683       }
6684   DataArrayInt *ret=DataArrayInt::New();
6685   ret->alloc(nbOfCells,1);
6686   int *retPtr=ret->getPointer();
6687   std::fill(retPtr,retPtr+nbOfCells,-1);
6688   int newCellId=0;
6689   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6690     {
6691       for(const int *i=connI;i!=connI+nbOfCells;i++)
6692         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6693           retPtr[std::distance(connI,i)]=newCellId++;
6694     }
6695   renumberCells(retPtr,false);
6696   return ret;
6697 }
6698
6699 /*!
6700  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6701  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6702  * This method makes asumption that connectivity is correctly set before calling.
6703  */
6704 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6705 {
6706   checkConnectivityFullyDefined();
6707   const int *conn=_nodal_connec->getConstPointer();
6708   const int *connI=_nodal_connec_index->getConstPointer();
6709   int nbOfCells=getNumberOfCells();
6710   std::vector<MEDCouplingUMesh *> ret;
6711   for(const int *i=connI;i!=connI+nbOfCells;)
6712     {
6713       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6714       int beginCellId=(int)std::distance(connI,i);
6715       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6716       int endCellId=(int)std::distance(connI,i);
6717       int sz=endCellId-beginCellId;
6718       int *cells=new int[sz];
6719       for(int j=0;j<sz;j++)
6720         cells[j]=beginCellId+j;
6721       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6722       delete [] cells;
6723       ret.push_back(m);
6724     }
6725   return ret;
6726 }
6727
6728 /*!
6729  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6730  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6731  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6732  *
6733  * \return a newly allocated instance, that the caller must manage.
6734  * \throw If \a this contains more than one geometric type.
6735  * \throw If the nodal connectivity of \a this is not fully defined.
6736  * \throw If the internal data is not coherent.
6737  */
6738 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6739 {
6740   checkConnectivityFullyDefined();
6741     if(_types.size()!=1)
6742     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6743   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6744   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6745   ret->setCoords(getCoords());
6746   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6747   if(retC)
6748     {
6749       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6750       retC->setNodalConnectivity(c);
6751     }
6752   else
6753     {
6754       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6755       if(!retD)
6756         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6757       DataArrayInt *c=0,*ci=0;
6758       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6759       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6760       retD->setNodalConnectivity(cs,cis);
6761     }
6762   return ret.retn();
6763 }
6764
6765 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6766 {
6767   checkConnectivityFullyDefined();
6768     if(_types.size()!=1)
6769     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6770   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6771   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6772   if(cm.isDynamic())
6773     {
6774       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6775       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6776       throw INTERP_KERNEL::Exception(oss.str().c_str());
6777     }
6778   int nbCells=getNumberOfCells();
6779   int typi=(int)typ;
6780   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6781   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6782   int *outPtr=connOut->getPointer();
6783   const int *conn=_nodal_connec->begin();
6784   const int *connI=_nodal_connec_index->begin();
6785   nbNodesPerCell++;
6786   for(int i=0;i<nbCells;i++,connI++)
6787     {
6788       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6789         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6790       else
6791         {
6792           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 << ") !";
6793           throw INTERP_KERNEL::Exception(oss.str().c_str());
6794         }
6795     }
6796   return connOut.retn();
6797 }
6798
6799 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6800 {
6801   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6802   checkConnectivityFullyDefined();
6803   if(_types.size()!=1)
6804     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6805   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6806   if(lgth<nbCells)
6807     throw INTERP_KERNEL::Exception(msg0);
6808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6809   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6810   int *cp(c->getPointer()),*cip(ci->getPointer());
6811   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6812   cip[0]=0;
6813   for(int i=0;i<nbCells;i++,cip++,incip++)
6814     {
6815       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6816       int delta(stop-strt);
6817       if(delta>=1)
6818         {
6819           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6820             cp=std::copy(incp+strt,incp+stop,cp);
6821           else
6822             throw INTERP_KERNEL::Exception(msg0);
6823         }
6824       else
6825         throw INTERP_KERNEL::Exception(msg0);
6826       cip[1]=cip[0]+delta;
6827     }
6828   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6829 }
6830
6831 /*!
6832  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6833  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6834  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6835  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6836  * are not used here to avoid the build of big permutation array.
6837  *
6838  * \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
6839  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6840  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6841  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6842  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6843  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6844  * \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
6845  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6846  */
6847 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6848                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6849                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6850 {
6851   std::vector<const MEDCouplingUMesh *> ms2;
6852   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6853     if(*it)
6854       {
6855         (*it)->checkConnectivityFullyDefined();
6856         ms2.push_back(*it);
6857       }
6858   if(ms2.empty())
6859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6860   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6861   int meshDim=ms2[0]->getMeshDimension();
6862   std::vector<const MEDCouplingUMesh *> m1ssm;
6863   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6864   //
6865   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6866   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6867   int fake=0,rk=0;
6868   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6869   ret1->alloc(0,1); ret2->alloc(0,1);
6870   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6871     {
6872       if(meshDim!=(*it)->getMeshDimension())
6873         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6874       if(refCoo!=(*it)->getCoords())
6875         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6876       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6877       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6878       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6879       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6880         {
6881           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6882           m1ssmSingleAuto.push_back(singleCell);
6883           m1ssmSingle.push_back(singleCell);
6884           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6885         }
6886     }
6887   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6888   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6889   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6890   for(std::size_t i=0;i<m1ssm.size();i++)
6891     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6892   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6893   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6894   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6895   return ret0.retn();
6896 }
6897
6898 /*!
6899  * This method returns a newly created DataArrayInt instance.
6900  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6901  */
6902 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6903 {
6904   checkFullyDefined();
6905   const int *conn=_nodal_connec->getConstPointer();
6906   const int *connIndex=_nodal_connec_index->getConstPointer();
6907   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6908   for(const int *w=begin;w!=end;w++)
6909     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6910       ret->pushBackSilent(*w);
6911   return ret.retn();
6912 }
6913
6914 /*!
6915  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6916  * are in [0:getNumberOfCells())
6917  */
6918 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6919 {
6920   checkFullyDefined();
6921   const int *conn=_nodal_connec->getConstPointer();
6922   const int *connI=_nodal_connec_index->getConstPointer();
6923   int nbOfCells=getNumberOfCells();
6924   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6925   int *tmp=new int[nbOfCells];
6926   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6927     {
6928       int j=0;
6929       for(const int *i=connI;i!=connI+nbOfCells;i++)
6930         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6931           tmp[std::distance(connI,i)]=j++;
6932     }
6933   DataArrayInt *ret=DataArrayInt::New();
6934   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6935   ret->copyStringInfoFrom(*da);
6936   int *retPtr=ret->getPointer();
6937   const int *daPtr=da->getConstPointer();
6938   int nbOfElems=da->getNbOfElems();
6939   for(int k=0;k<nbOfElems;k++)
6940     retPtr[k]=tmp[daPtr[k]];
6941   delete [] tmp;
6942   return ret;
6943 }
6944
6945 /*!
6946  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6947  * This method \b works \b for mesh sorted by type.
6948  * cells whose ids is in 'idsPerGeoType' array.
6949  * This method conserves coords and name of mesh.
6950  */
6951 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6952 {
6953   std::vector<int> code=getDistributionOfTypes();
6954   std::size_t nOfTypesInThis=code.size()/3;
6955   int sz=0,szOfType=0;
6956   for(std::size_t i=0;i<nOfTypesInThis;i++)
6957     {
6958       if(code[3*i]!=type)
6959         sz+=code[3*i+1];
6960       else
6961         szOfType=code[3*i+1];
6962     }
6963   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6964     if(*work<0 || *work>=szOfType)
6965       {
6966         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6967         oss << ". It should be in [0," << szOfType << ") !";
6968         throw INTERP_KERNEL::Exception(oss.str().c_str());
6969       }
6970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6971   int *idsPtr=idsTokeep->getPointer();
6972   int offset=0;
6973   for(std::size_t i=0;i<nOfTypesInThis;i++)
6974     {
6975       if(code[3*i]!=type)
6976         for(int j=0;j<code[3*i+1];j++)
6977           *idsPtr++=offset+j;
6978       else
6979         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6980       offset+=code[3*i+1];
6981     }
6982   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6983   ret->copyTinyInfoFrom(this);
6984   return ret.retn();
6985 }
6986
6987 /*!
6988  * This method returns a vector of size 'this->getNumberOfCells()'.
6989  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6990  */
6991 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6992 {
6993   int ncell=getNumberOfCells();
6994   std::vector<bool> ret(ncell);
6995   const int *cI=getNodalConnectivityIndex()->getConstPointer();
6996   const int *c=getNodalConnectivity()->getConstPointer();
6997   for(int i=0;i<ncell;i++)
6998     {
6999       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7000       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7001       ret[i]=cm.isQuadratic();
7002     }
7003   return ret;
7004 }
7005
7006 /*!
7007  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7008  */
7009 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7010 {
7011   if(other->getType()!=UNSTRUCTURED)
7012     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7013   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7014   return MergeUMeshes(this,otherC);
7015 }
7016
7017 /*!
7018  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7019  * computed by averaging coordinates of cell nodes, so this method is not a right
7020  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7021  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7022  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7023  *          components. The caller is to delete this array using decrRef() as it is
7024  *          no more needed.
7025  *  \throw If the coordinates array is not set.
7026  *  \throw If the nodal connectivity of cells is not defined.
7027  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7028  */
7029 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7030 {
7031   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7032   int spaceDim=getSpaceDimension();
7033   int nbOfCells=getNumberOfCells();
7034   ret->alloc(nbOfCells,spaceDim);
7035   ret->copyStringInfoFrom(*getCoords());
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++)
7041     {
7042       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7043       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7044       ptToFill+=spaceDim;
7045     }
7046   return ret.retn();
7047 }
7048
7049 /*!
7050  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7051  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7052  * 
7053  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7054  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7055  * 
7056  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7057  * \throw If \a this is not fully defined (coordinates and connectivity)
7058  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7059  */
7060 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7061 {
7062   checkFullyDefined();
7063   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7064   int spaceDim=getSpaceDimension();
7065   int nbOfCells=getNumberOfCells();
7066   int nbOfNodes=getNumberOfNodes();
7067   ret->alloc(nbOfCells,spaceDim);
7068   double *ptToFill=ret->getPointer();
7069   const int *nodal=_nodal_connec->getConstPointer();
7070   const int *nodalI=_nodal_connec_index->getConstPointer();
7071   const double *coor=_coords->getConstPointer();
7072   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7073     {
7074       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7075       std::fill(ptToFill,ptToFill+spaceDim,0.);
7076       if(type!=INTERP_KERNEL::NORM_POLYHED)
7077         {
7078           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7079             {
7080               if(*conn>=0 && *conn<nbOfNodes)
7081                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7082               else
7083                 {
7084                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7085                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7086                 }
7087             }
7088           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7089           if(nbOfNodesInCell>0)
7090             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7091           else
7092             {
7093               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7094               throw INTERP_KERNEL::Exception(oss.str().c_str());
7095             }
7096         }
7097       else
7098         {
7099           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7100           s.erase(-1);
7101           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7102             {
7103               if(*it>=0 && *it<nbOfNodes)
7104                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7105               else
7106                 {
7107                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7108                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7109                 }
7110             }
7111           if(!s.empty())
7112             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7113           else
7114             {
7115               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7116               throw INTERP_KERNEL::Exception(oss.str().c_str());
7117             }
7118         }
7119     }
7120   return ret.retn();
7121 }
7122
7123 /*!
7124  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7125  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7126  * are specified via an array of cell ids. 
7127  *  \warning Validity of the specified cell ids is not checked! 
7128  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7129  *  \param [in] begin - an array of cell ids of interest.
7130  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7131  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7132  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7133  *          caller is to delete this array using decrRef() as it is no more needed. 
7134  *  \throw If the coordinates array is not set.
7135  *  \throw If the nodal connectivity of cells is not defined.
7136  *
7137  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7138  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7139  */
7140 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7141 {
7142   DataArrayDouble *ret=DataArrayDouble::New();
7143   int spaceDim=getSpaceDimension();
7144   int nbOfTuple=(int)std::distance(begin,end);
7145   ret->alloc(nbOfTuple,spaceDim);
7146   double *ptToFill=ret->getPointer();
7147   double *tmp=new double[spaceDim];
7148   const int *nodal=_nodal_connec->getConstPointer();
7149   const int *nodalI=_nodal_connec_index->getConstPointer();
7150   const double *coor=_coords->getConstPointer();
7151   for(const int *w=begin;w!=end;w++)
7152     {
7153       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7154       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7155       ptToFill+=spaceDim;
7156     }
7157   delete [] tmp;
7158   return ret;
7159 }
7160
7161 /*!
7162  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7163  * 
7164  */
7165 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7166 {
7167   if(!da)
7168     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7169   da->checkAllocated();
7170   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7171   ret->setCoords(da);
7172   int nbOfTuples=da->getNumberOfTuples();
7173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7175   c->alloc(2*nbOfTuples,1);
7176   cI->alloc(nbOfTuples+1,1);
7177   int *cp=c->getPointer();
7178   int *cip=cI->getPointer();
7179   *cip++=0;
7180   for(int i=0;i<nbOfTuples;i++)
7181     {
7182       *cp++=INTERP_KERNEL::NORM_POINT1;
7183       *cp++=i;
7184       *cip++=2*(i+1);
7185     }
7186   ret->setConnectivity(c,cI,true);
7187   return ret.retn();
7188 }
7189 /*!
7190  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7191  * Cells and nodes of
7192  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7193  *  \param [in] mesh1 - the first mesh.
7194  *  \param [in] mesh2 - the second mesh.
7195  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7196  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7197  *          is no more needed.
7198  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7199  *  \throw If the coordinates array is not set in none of the meshes.
7200  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7201  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7202  */
7203 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7204 {
7205   std::vector<const MEDCouplingUMesh *> tmp(2);
7206   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7207   return MergeUMeshes(tmp);
7208 }
7209
7210 /*!
7211  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7212  * Cells and nodes of
7213  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7214  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7215  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7216  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7217  *          is no more needed.
7218  *  \throw If \a a.size() == 0.
7219  *  \throw If \a a[ *i* ] == NULL.
7220  *  \throw If the coordinates array is not set in none of the meshes.
7221  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7222  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7223 */
7224 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7225 {
7226   std::size_t sz=a.size();
7227   if(sz==0)
7228     return MergeUMeshesLL(a);
7229   for(std::size_t ii=0;ii<sz;ii++)
7230     if(!a[ii])
7231       {
7232         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7233         throw INTERP_KERNEL::Exception(oss.str().c_str());
7234       }
7235   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7236   std::vector< const MEDCouplingUMesh * > aa(sz);
7237   int spaceDim=-3;
7238   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7239     {
7240       const MEDCouplingUMesh *cur=a[i];
7241       const DataArrayDouble *coo=cur->getCoords();
7242       if(coo)
7243         spaceDim=coo->getNumberOfComponents();
7244     }
7245   if(spaceDim==-3)
7246     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7247   for(std::size_t i=0;i<sz;i++)
7248     {
7249       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7250       aa[i]=bb[i];
7251     }
7252   return MergeUMeshesLL(aa);
7253 }
7254
7255 /// @cond INTERNAL
7256
7257 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7258 {
7259   if(a.empty())
7260     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7261   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7262   int meshDim=(*it)->getMeshDimension();
7263   int nbOfCells=(*it)->getNumberOfCells();
7264   int meshLgth=(*it++)->getMeshLength();
7265   for(;it!=a.end();it++)
7266     {
7267       if(meshDim!=(*it)->getMeshDimension())
7268         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7269       nbOfCells+=(*it)->getNumberOfCells();
7270       meshLgth+=(*it)->getMeshLength();
7271     }
7272   std::vector<const MEDCouplingPointSet *> aps(a.size());
7273   std::copy(a.begin(),a.end(),aps.begin());
7274   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7275   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7276   ret->setCoords(pts);
7277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7278   c->alloc(meshLgth,1);
7279   int *cPtr=c->getPointer();
7280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7281   cI->alloc(nbOfCells+1,1);
7282   int *cIPtr=cI->getPointer();
7283   *cIPtr++=0;
7284   int offset=0;
7285   int offset2=0;
7286   for(it=a.begin();it!=a.end();it++)
7287     {
7288       int curNbOfCell=(*it)->getNumberOfCells();
7289       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7290       const int *curC=(*it)->_nodal_connec->getConstPointer();
7291       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7292       for(int j=0;j<curNbOfCell;j++)
7293         {
7294           const int *src=curC+curCI[j];
7295           *cPtr++=*src++;
7296           for(;src!=curC+curCI[j+1];src++,cPtr++)
7297             {
7298               if(*src!=-1)
7299                 *cPtr=*src+offset2;
7300               else
7301                 *cPtr=-1;
7302             }
7303         }
7304       offset+=curCI[curNbOfCell];
7305       offset2+=(*it)->getNumberOfNodes();
7306     }
7307   //
7308   ret->setConnectivity(c,cI,true);
7309   return ret.retn();
7310 }
7311
7312 /// @endcond
7313
7314 /*!
7315  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7316  * dimension and sharing the node coordinates array.
7317  * All cells of the first mesh precede all cells of the second mesh
7318  * within the result mesh. 
7319  *  \param [in] mesh1 - the first mesh.
7320  *  \param [in] mesh2 - the second mesh.
7321  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7322  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7323  *          is no more needed.
7324  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7325  *  \throw If the meshes do not share the node coordinates array.
7326  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7327  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7328  */
7329 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7330 {
7331   std::vector<const MEDCouplingUMesh *> tmp(2);
7332   tmp[0]=mesh1; tmp[1]=mesh2;
7333   return MergeUMeshesOnSameCoords(tmp);
7334 }
7335
7336 /*!
7337  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7338  * dimension and sharing the node coordinates array.
7339  * All cells of the *i*-th mesh precede all cells of the
7340  * (*i*+1)-th mesh within the result mesh.
7341  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7342  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7343  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7344  *          is no more needed.
7345  *  \throw If \a a.size() == 0.
7346  *  \throw If \a a[ *i* ] == NULL.
7347  *  \throw If the meshes do not share the node coordinates array.
7348  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7349  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7350  */
7351 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7352 {
7353   if(meshes.empty())
7354     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7355   for(std::size_t ii=0;ii<meshes.size();ii++)
7356     if(!meshes[ii])
7357       {
7358         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7359         throw INTERP_KERNEL::Exception(oss.str().c_str());
7360       }
7361   const DataArrayDouble *coords=meshes.front()->getCoords();
7362   int meshDim=meshes.front()->getMeshDimension();
7363   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7364   int meshLgth=0;
7365   int meshIndexLgth=0;
7366   for(;iter!=meshes.end();iter++)
7367     {
7368       if(coords!=(*iter)->getCoords())
7369         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7370       if(meshDim!=(*iter)->getMeshDimension())
7371         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7372       meshLgth+=(*iter)->getMeshLength();
7373       meshIndexLgth+=(*iter)->getNumberOfCells();
7374     }
7375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7376   nodal->alloc(meshLgth,1);
7377   int *nodalPtr=nodal->getPointer();
7378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7379   nodalIndex->alloc(meshIndexLgth+1,1);
7380   int *nodalIndexPtr=nodalIndex->getPointer();
7381   int offset=0;
7382   for(iter=meshes.begin();iter!=meshes.end();iter++)
7383     {
7384       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7385       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7386       int nbOfCells=(*iter)->getNumberOfCells();
7387       int meshLgth2=(*iter)->getMeshLength();
7388       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7389       if(iter!=meshes.begin())
7390         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7391       else
7392         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7393       offset+=meshLgth2;
7394     }
7395   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7396   ret->setName("merge");
7397   ret->setMeshDimension(meshDim);
7398   ret->setConnectivity(nodal,nodalIndex,true);
7399   ret->setCoords(coords);
7400   return ret;
7401 }
7402
7403 /*!
7404  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7405  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7406  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7407  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7408  * New" mode are returned for each input mesh.
7409  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7410  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7411  *          valid values [0,1,2], see zipConnectivityTraducer().
7412  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7413  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7414  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7415  *          no more needed.
7416  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7417  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7418  *          is no more needed.
7419  *  \throw If \a meshes.size() == 0.
7420  *  \throw If \a meshes[ *i* ] == NULL.
7421  *  \throw If the meshes do not share the node coordinates array.
7422  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7423  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7424  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7425  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7426  */
7427 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7428 {
7429   //All checks are delegated to MergeUMeshesOnSameCoords
7430   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7432   corr.resize(meshes.size());
7433   std::size_t nbOfMeshes=meshes.size();
7434   int offset=0;
7435   const int *o2nPtr=o2n->getConstPointer();
7436   for(std::size_t i=0;i<nbOfMeshes;i++)
7437     {
7438       DataArrayInt *tmp=DataArrayInt::New();
7439       int curNbOfCells=meshes[i]->getNumberOfCells();
7440       tmp->alloc(curNbOfCells,1);
7441       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7442       offset+=curNbOfCells;
7443       tmp->setName(meshes[i]->getName().c_str());
7444       corr[i]=tmp;
7445     }
7446   return ret.retn();
7447 }
7448
7449 /*!
7450  * Makes all given meshes share the nodal connectivity array. The common connectivity
7451  * array is created by concatenating the connectivity arrays of all given meshes. All
7452  * the given meshes must be of the same space dimension but dimension of cells **can
7453  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7454  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7455  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7456  *  \param [in,out] meshes - a vector of meshes to update.
7457  *  \throw If any of \a meshes is NULL.
7458  *  \throw If the coordinates array is not set in any of \a meshes.
7459  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7460  *  \throw If \a meshes are of different space dimension.
7461  */
7462 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7463 {
7464   std::size_t sz=meshes.size();
7465   if(sz==0 || sz==1)
7466     return;
7467   std::vector< const DataArrayDouble * > coords(meshes.size());
7468   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7469   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7470     {
7471       if((*it))
7472         {
7473           (*it)->checkConnectivityFullyDefined();
7474           const DataArrayDouble *coo=(*it)->getCoords();
7475           if(coo)
7476             *it2=coo;
7477           else
7478             {
7479               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7480               oss << " has no coordinate array defined !";
7481               throw INTERP_KERNEL::Exception(oss.str().c_str());
7482             }
7483         }
7484       else
7485         {
7486           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7487           oss << " is null !";
7488           throw INTERP_KERNEL::Exception(oss.str().c_str());
7489         }
7490     }
7491   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7492   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7493   int offset=(*it)->getNumberOfNodes();
7494   (*it++)->setCoords(res);
7495   for(;it!=meshes.end();it++)
7496     {
7497       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7498       (*it)->setCoords(res);
7499       (*it)->shiftNodeNumbersInConn(offset);
7500       offset+=oldNumberOfNodes;
7501     }
7502 }
7503
7504 /*!
7505  * Merges nodes coincident with a given precision within all given meshes that share
7506  * the nodal connectivity array. The given meshes **can be of different** mesh
7507  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7508  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7509  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7510  *  \param [in,out] meshes - a vector of meshes to update.
7511  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7512  *  \throw If any of \a meshes is NULL.
7513  *  \throw If the \a meshes do not share the same node coordinates array.
7514  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7515  */
7516 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7517 {
7518   if(meshes.empty())
7519     return ;
7520   std::set<const DataArrayDouble *> s;
7521   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7522     {
7523       if(*it)
7524         s.insert((*it)->getCoords());
7525       else
7526         {
7527           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 !";
7528           throw INTERP_KERNEL::Exception(oss.str().c_str());
7529         }
7530     }
7531   if(s.size()!=1)
7532     {
7533       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 !";
7534       throw INTERP_KERNEL::Exception(oss.str().c_str());
7535     }
7536   const DataArrayDouble *coo=*(s.begin());
7537   if(!coo)
7538     return;
7539   //
7540   DataArrayInt *comm,*commI;
7541   coo->findCommonTuples(eps,-1,comm,commI);
7542   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7543   int oldNbOfNodes=coo->getNumberOfTuples();
7544   int newNbOfNodes;
7545   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7546   if(oldNbOfNodes==newNbOfNodes)
7547     return ;
7548   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7549   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7550     {
7551       (*it)->renumberNodesInConn(o2n->getConstPointer());
7552       (*it)->setCoords(newCoords);
7553     } 
7554 }
7555
7556 /*!
7557  * 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.
7558  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7559  * \param isQuad specifies the policy of connectivity.
7560  * @ret in/out parameter in which the result will be append
7561  */
7562 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7563 {
7564   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7565   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7566   ret.push_back(cm.getExtrudedType());
7567   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7568   switch(flatType)
7569     {
7570     case INTERP_KERNEL::NORM_POINT1:
7571       {
7572         ret.push_back(connBg[1]);
7573         ret.push_back(connBg[1]+nbOfNodesPerLev);
7574         break;
7575       }
7576     case INTERP_KERNEL::NORM_SEG2:
7577       {
7578         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7579         ret.insert(ret.end(),conn,conn+4);
7580         break;
7581       }
7582     case INTERP_KERNEL::NORM_SEG3:
7583       {
7584         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7585         ret.insert(ret.end(),conn,conn+8);
7586         break;
7587       }
7588     case INTERP_KERNEL::NORM_QUAD4:
7589       {
7590         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7591         ret.insert(ret.end(),conn,conn+8);
7592         break;
7593       }
7594     case INTERP_KERNEL::NORM_TRI3:
7595       {
7596         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7597         ret.insert(ret.end(),conn,conn+6);
7598         break;
7599       }
7600     case INTERP_KERNEL::NORM_TRI6:
7601       {
7602         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,
7603                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7604         ret.insert(ret.end(),conn,conn+15);
7605         break;
7606       }
7607     case INTERP_KERNEL::NORM_QUAD8:
7608       {
7609         int conn[20]={
7610           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7611           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7612           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7613         };
7614         ret.insert(ret.end(),conn,conn+20);
7615         break;
7616       }
7617     case INTERP_KERNEL::NORM_POLYGON:
7618       {
7619         std::back_insert_iterator< std::vector<int> > ii(ret);
7620         std::copy(connBg+1,connEnd,ii);
7621         *ii++=-1;
7622         std::reverse_iterator<const int *> rConnBg(connEnd);
7623         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7624         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7625         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7626         for(std::size_t i=0;i<nbOfRadFaces;i++)
7627           {
7628             *ii++=-1;
7629             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7630             std::copy(conn,conn+4,ii);
7631           }
7632         break;
7633       }
7634     default:
7635       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7636     }
7637 }
7638
7639 /*!
7640  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7641  */
7642 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7643 {
7644   double v[3]={0.,0.,0.};
7645   std::size_t sz=std::distance(begin,end);
7646   if(isQuadratic)
7647     sz/=2;
7648   for(std::size_t i=0;i<sz;i++)
7649     {
7650       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];
7651       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7652       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7653     }
7654   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7655 }
7656
7657 /*!
7658  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7659  */
7660 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7661 {
7662   std::vector<std::pair<int,int> > edges;
7663   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7664   const int *bgFace=begin;
7665   for(std::size_t i=0;i<nbOfFaces;i++)
7666     {
7667       const int *endFace=std::find(bgFace+1,end,-1);
7668       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7669       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7670         {
7671           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7672           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7673             return false;
7674           edges.push_back(p1);
7675         }
7676       bgFace=endFace+1;
7677     }
7678   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7679 }
7680
7681 /*!
7682  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7683  */
7684 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7685 {
7686   double vec0[3],vec1[3];
7687   std::size_t sz=std::distance(begin,end);
7688   if(sz%2!=0)
7689     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7690   int nbOfNodes=(int)sz/2;
7691   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7692   const double *pt0=coords+3*begin[0];
7693   const double *pt1=coords+3*begin[nbOfNodes];
7694   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7695   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7696 }
7697
7698 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7699 {
7700   std::size_t sz=std::distance(begin,end);
7701   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7702   std::size_t nbOfNodes(sz/2);
7703   std::copy(begin,end,(int *)tmp);
7704   for(std::size_t j=1;j<nbOfNodes;j++)
7705     {
7706       begin[j]=tmp[nbOfNodes-j];
7707       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7708     }
7709 }
7710
7711 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7712 {
7713   std::size_t sz=std::distance(begin,end);
7714   if(sz!=4)
7715     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7716   double vec0[3],vec1[3];
7717   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7718   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]; 
7719   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;
7720 }
7721
7722 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7723 {
7724   std::size_t sz=std::distance(begin,end);
7725   if(sz!=5)
7726     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7727   double vec0[3];
7728   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7729   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7730   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7731 }
7732
7733 /*!
7734  * 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 ) 
7735  * 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
7736  * a 2D space.
7737  *
7738  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7739  * \param [in] coords the coordinates with nb of components exactly equal to 3
7740  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7741  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7742  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7743  */
7744 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7745 {
7746   int nbFaces=std::count(begin+1,end,-1)+1;
7747   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7748   double *vPtr=v->getPointer();
7749   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7750   double *pPtr=p->getPointer();
7751   const int *stFaceConn=begin+1;
7752   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7753     {
7754       const int *endFaceConn=std::find(stFaceConn,end,-1);
7755       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7756       stFaceConn=endFaceConn+1;
7757     }
7758   pPtr=p->getPointer(); vPtr=v->getPointer();
7759   DataArrayInt *comm1=0,*commI1=0;
7760   v->findCommonTuples(eps,-1,comm1,commI1);
7761   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7762   const int *comm1Ptr=comm1->getConstPointer();
7763   const int *commI1Ptr=commI1->getConstPointer();
7764   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7765   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7766   //
7767   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7768   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7769   mm->finishInsertingCells();
7770   //
7771   for(int i=0;i<nbOfGrps1;i++)
7772     {
7773       int vecId=comm1Ptr[commI1Ptr[i]];
7774       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7775       DataArrayInt *comm2=0,*commI2=0;
7776       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7777       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7778       const int *comm2Ptr=comm2->getConstPointer();
7779       const int *commI2Ptr=commI2->getConstPointer();
7780       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7781       for(int j=0;j<nbOfGrps2;j++)
7782         {
7783           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7784             {
7785               res->insertAtTheEnd(begin,end);
7786               res->pushBackSilent(-1);
7787             }
7788           else
7789             {
7790               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7791               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7792               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7793               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7794               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7795               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7796               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7797               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7798               const int *idsNodePtr=idsNode->getConstPointer();
7799               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];
7800               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7801               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7802               if(std::abs(norm)>eps)
7803                 {
7804                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7805                   mm3->rotate(center,vec,angle);
7806                 }
7807               mm3->changeSpaceDimension(2);
7808               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7809               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7810               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7811               int nbOfCells=mm4->getNumberOfCells();
7812               for(int k=0;k<nbOfCells;k++)
7813                 {
7814                   int l=0;
7815                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7816                     res->pushBackSilent(idsNodePtr[*work]);
7817                   res->pushBackSilent(-1);
7818                 }
7819             }
7820         }
7821     }
7822   res->popBackSilent();
7823 }
7824
7825 /*!
7826  * 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
7827  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7828  * 
7829  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7830  * \param [in] coords coordinates expected to have 3 components.
7831  * \param [in] begin start of the nodal connectivity of the face.
7832  * \param [in] end end of the nodal connectivity (excluded) of the face.
7833  * \param [out] v the normalized vector of size 3
7834  * \param [out] p the pos of plane
7835  */
7836 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7837 {
7838   std::size_t nbPoints=std::distance(begin,end);
7839   if(nbPoints<3)
7840     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7841   double vec[3]={0.,0.,0.};
7842   std::size_t j=0;
7843   bool refFound=false;
7844   for(;j<nbPoints-1 && !refFound;j++)
7845     {
7846       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7847       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7848       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7849       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7850       if(norm>eps)
7851         {
7852           refFound=true;
7853           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7854         }
7855     }
7856   for(std::size_t i=j;i<nbPoints-1;i++)
7857     {
7858       double curVec[3];
7859       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7860       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7861       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7862       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7863       if(norm<eps)
7864         continue;
7865       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7866       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];
7867       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7868       if(norm>eps)
7869         {
7870           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7871           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7872           return ;
7873         }
7874     }
7875   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7876 }
7877
7878 /*!
7879  * This method tries to obtain a well oriented polyhedron.
7880  * If the algorithm fails, an exception will be thrown.
7881  */
7882 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7883 {
7884   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7885   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7886   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7887   isPerm[0]=true;
7888   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7889   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7890   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7891   //
7892   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7893     {
7894       bgFace=begin;
7895       std::size_t smthChanged=0;
7896       for(std::size_t i=0;i<nbOfFaces;i++)
7897         {
7898           endFace=std::find(bgFace+1,end,-1);
7899           nbOfEdgesInFace=std::distance(bgFace,endFace);
7900           if(!isPerm[i])
7901             {
7902               bool b;
7903               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7904                 {
7905                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7906                   std::pair<int,int> p2(p1.second,p1.first);
7907                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7908                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7909                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7910                 }
7911               if(isPerm[i])
7912                 { 
7913                   if(!b)
7914                     std::reverse(bgFace+1,endFace);
7915                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7916                     {
7917                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7918                       std::pair<int,int> p2(p1.second,p1.first);
7919                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7920                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7921                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7922                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7923                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7924                       if(it!=edgesOK.end())
7925                         {
7926                           edgesOK.erase(it);
7927                           edgesFinished.push_back(p1);
7928                         }
7929                       else
7930                         edgesOK.push_back(p1);
7931                     }
7932                 }
7933             }
7934           bgFace=endFace+1;
7935         }
7936       if(smthChanged==0)
7937         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7938     }
7939   if(!edgesOK.empty())
7940     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7941   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7942     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7943       bgFace=begin;
7944       for(std::size_t i=0;i<nbOfFaces;i++)
7945         {
7946           endFace=std::find(bgFace+1,end,-1);
7947           std::reverse(bgFace+1,endFace);
7948           bgFace=endFace+1;
7949         }
7950     }
7951 }
7952
7953 /*!
7954  * This method makes the assumption spacedimension == meshdimension == 2.
7955  * This method works only for linear cells.
7956  * 
7957  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7958  */
7959 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7960 {
7961   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7962     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7963   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7964   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7965   int nbOfNodesExpected=m->getNumberOfNodes();
7966   if(m->getNumberOfCells()!=nbOfNodesExpected)
7967     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7968   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7969   const int *n2oPtr=n2o->getConstPointer();
7970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7971   m->getReverseNodalConnectivity(revNodal,revNodalI);
7972   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7973   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7974   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7976   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7977   if(nbOfNodesExpected<1)
7978     return ret.retn();
7979   int prevCell=0;
7980   int prevNode=nodalPtr[nodalIPtr[0]+1];
7981   *work++=n2oPtr[prevNode];
7982   for(int i=1;i<nbOfNodesExpected;i++)
7983     {
7984       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7985         {
7986           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7987           conn.erase(prevNode);
7988           if(conn.size()==1)
7989             {
7990               int curNode=*(conn.begin());
7991               *work++=n2oPtr[curNode];
7992               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7993               shar.erase(prevCell);
7994               if(shar.size()==1)
7995                 {
7996                   prevCell=*(shar.begin());
7997                   prevNode=curNode;
7998                 }
7999               else
8000                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8001             }
8002           else
8003             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8004         }
8005       else
8006         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8007     }
8008   return ret.retn();
8009 }
8010
8011 /*!
8012  * This method makes the assumption spacedimension == meshdimension == 3.
8013  * This method works only for linear cells.
8014  * 
8015  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8016  */
8017 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8018 {
8019   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8020     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8021   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8022   const int *conn=m->getNodalConnectivity()->getConstPointer();
8023   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8024   int nbOfCells=m->getNumberOfCells();
8025   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8026   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8027   if(nbOfCells<1)
8028     return ret.retn();
8029   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8030   for(int i=1;i<nbOfCells;i++)
8031     {
8032       *work++=-1;
8033       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8034     }
8035   return ret.retn();
8036 }
8037
8038 /*!
8039  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8040  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8041  */
8042 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8043 {
8044   double *w=zipFrmt;
8045   if(spaceDim==3)
8046     for(int i=0;i<nbOfNodesInCell;i++)
8047       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8048   else if(spaceDim==2)
8049     {
8050       for(int i=0;i<nbOfNodesInCell;i++)
8051         {
8052           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8053           *w++=0.;
8054         }
8055     }
8056   else
8057     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8058 }
8059
8060 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8061 {
8062   int nbOfCells=getNumberOfCells();
8063   if(nbOfCells<=0)
8064     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8065   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};
8066   ofs << "  <" << getVTKDataSetType() << ">\n";
8067   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8068   ofs << "      <PointData>\n" << pointData << std::endl;
8069   ofs << "      </PointData>\n";
8070   ofs << "      <CellData>\n" << cellData << std::endl;
8071   ofs << "      </CellData>\n";
8072   ofs << "      <Points>\n";
8073   if(getSpaceDimension()==3)
8074     _coords->writeVTK(ofs,8,"Points");
8075   else
8076     {
8077       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8078       coo->writeVTK(ofs,8,"Points");
8079     }
8080   ofs << "      </Points>\n";
8081   ofs << "      <Cells>\n";
8082   const int *cPtr=_nodal_connec->getConstPointer();
8083   const int *cIPtr=_nodal_connec_index->getConstPointer();
8084   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8085   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8086   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8087   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8088   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8089   int szFaceOffsets=0,szConn=0;
8090   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8091     {
8092       *w2=cPtr[cIPtr[i]];
8093       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8094         {
8095           *w1=-1;
8096           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8097           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8098         }
8099       else
8100         {
8101           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8102           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8103           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8104           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8105           w4=std::copy(c.begin(),c.end(),w4);
8106         }
8107     }
8108   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8109   types->writeVTK(ofs,8,"UInt8","types");
8110   offsets->writeVTK(ofs,8,"Int32","offsets");
8111   if(szFaceOffsets!=0)
8112     {//presence of Polyhedra
8113       connectivity->reAlloc(szConn);
8114       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8115       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8116       w1=faces->getPointer();
8117       for(int i=0;i<nbOfCells;i++)
8118         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8119           {
8120             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8121             *w1++=nbFaces;
8122             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8123             for(int j=0;j<nbFaces;j++)
8124               {
8125                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8126                 *w1++=(int)std::distance(w6,w5);
8127                 w1=std::copy(w6,w5,w1);
8128                 w6=w5+1;
8129               }
8130           }
8131       faces->writeVTK(ofs,8,"Int32","faces");
8132     }
8133   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8134   ofs << "      </Cells>\n";
8135   ofs << "    </Piece>\n";
8136   ofs << "  </" << getVTKDataSetType() << ">\n";
8137 }
8138
8139 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8140 {
8141   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8142   if(_mesh_dim==-2)
8143     { stream << " Not set !"; return ; }
8144   stream << " Mesh dimension : " << _mesh_dim << ".";
8145   if(_mesh_dim==-1)
8146     return ;
8147   if(!_coords)
8148     { stream << " No coordinates set !"; return ; }
8149   if(!_coords->isAllocated())
8150     { stream << " Coordinates set but not allocated !"; return ; }
8151   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8152   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8153   if(!_nodal_connec_index)
8154     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8155   if(!_nodal_connec_index->isAllocated())
8156     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8157   int lgth=_nodal_connec_index->getNumberOfTuples();
8158   int cpt=_nodal_connec_index->getNumberOfComponents();
8159   if(cpt!=1 || lgth<1)
8160     return ;
8161   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8162 }
8163
8164 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8165 {
8166   return std::string("UnstructuredGrid");
8167 }
8168
8169 /*!
8170  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8171  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8172  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8173  * meshes.
8174  *  \param [in] m1 - the first input mesh which is a partitioned object.
8175  *  \param [in] m2 - the second input mesh which is a partition tool.
8176  *  \param [in] eps - precision used to detect coincident mesh entities.
8177  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8178  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8179  *         this array using decrRef() as it is no more needed.
8180  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8181  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8182  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8183  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8184  *         it is no more needed.  
8185  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8186  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8187  *         is no more needed.  
8188  *  \throw If the coordinates array is not set in any of the meshes.
8189  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8190  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8191  */
8192 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8193 {
8194   m1->checkFullyDefined();
8195   m2->checkFullyDefined();
8196   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8197     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8198   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8199   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8200   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8201   std::vector<double> addCoo,addCoordsQuadratic;
8202   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8203   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8204   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8205                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8206   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8207   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8208   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8209   std::vector< std::vector<int> > intersectEdge2;
8210   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8211   subDiv2.clear(); dd5=0; dd6=0;
8212   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8213   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8214   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8215                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8216   //
8217   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8218   addCooDa->alloc((int)(addCoo.size())/2,2);
8219   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8220   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8221   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8222   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8223   std::vector<const DataArrayDouble *> coordss(4);
8224   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8225   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8226   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8227   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8228   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8229   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8230   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8231   ret->setConnectivity(conn,connI,true);
8232   ret->setCoords(coo);
8233   cellNb1=c1.retn(); cellNb2=c2.retn();
8234   return ret.retn();
8235 }
8236
8237 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8238                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8239                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8240                                                          const std::vector<double>& addCoords,
8241                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8242 {
8243   static const int SPACEDIM=2;
8244   std::vector<double> bbox1,bbox2;
8245   const double *coo1=m1->getCoords()->getConstPointer();
8246   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8247   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8248   int offset1=m1->getNumberOfNodes();
8249   const double *coo2=m2->getCoords()->getConstPointer();
8250   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8251   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8252   int offset2=offset1+m2->getNumberOfNodes();
8253   int offset3=offset2+((int)addCoords.size())/2;
8254   m1->getBoundingBoxForBBTree(bbox1);
8255   m2->getBoundingBoxForBBTree(bbox2);
8256   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8257   int ncell1=m1->getNumberOfCells();
8258   crI.push_back(0);
8259   for(int i=0;i<ncell1;i++)
8260     {
8261       std::vector<int> candidates2;
8262       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8263       std::map<INTERP_KERNEL::Node *,int> mapp;
8264       std::map<int,INTERP_KERNEL::Node *> mappRev;
8265       INTERP_KERNEL::QuadraticPolygon pol1;
8266       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8267       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8268       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8269       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8270                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8271       //
8272       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
8273       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8274       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8275       for(it1.first();!it1.finished();it1.next())
8276         edges1.insert(it1.current()->getPtr());
8277       //
8278       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8279       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8280       int ii=0;
8281       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8282         {
8283           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8284           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8285           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8286           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8287                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8288         }
8289       ii=0;
8290       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8291         {
8292           pol1.initLocationsWithOther(pol2s[ii]);
8293           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8294           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8295           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8296         }
8297       if(!edges1.empty())
8298         {
8299           try
8300             {
8301               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8302             }
8303           catch(INTERP_KERNEL::Exception& e)
8304             {
8305               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();
8306               throw INTERP_KERNEL::Exception(oss.str().c_str());
8307             }
8308         }
8309       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8310         (*it).second->decrRef();
8311     }
8312 }
8313
8314 /*!
8315  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8316  * 
8317  */
8318 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8319                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8320                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8321                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8322                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8323 {
8324   static const int SPACEDIM=2;
8325   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8326   desc2=DataArrayInt::New();
8327   descIndx2=DataArrayInt::New();
8328   revDesc2=DataArrayInt::New();
8329   revDescIndx2=DataArrayInt::New();
8330   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8332   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8333   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8334   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8335   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8336   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8337   std::vector<double> bbox1,bbox2;
8338   m1Desc->getBoundingBoxForBBTree(bbox1);
8339   m2Desc->getBoundingBoxForBBTree(bbox2);
8340   int ncell1=m1Desc->getNumberOfCells();
8341   int ncell2=m2Desc->getNumberOfCells();
8342   intersectEdge1.resize(ncell1);
8343   colinear2.resize(ncell2);
8344   subDiv2.resize(ncell2);
8345   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8346   std::vector<int> candidates1(1);
8347   int offset1=m1->getNumberOfNodes();
8348   int offset2=offset1+m2->getNumberOfNodes();
8349   for(int i=0;i<ncell1;i++)
8350     {
8351       std::vector<int> candidates2;
8352       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8353       if(!candidates2.empty())
8354         {
8355           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8356           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8357           candidates1[0]=i;
8358           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8359           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8360           delete pol2;
8361           delete pol1;
8362         }
8363       else
8364         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8365     }
8366   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8367   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8368 }
8369
8370 /*!
8371  * This method performs the 2nd step of Partition of 2D mesh.
8372  * This method has 4 inputs :
8373  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8374  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8375  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8376  * 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'
8377  * \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'
8378  * \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.
8379  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8380  */
8381 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)
8382 {
8383   int offset1=m1->getNumberOfNodes();
8384   int ncell=m2->getNumberOfCells();
8385   const int *c=m2->getNodalConnectivity()->getConstPointer();
8386   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8387   const double *coo=m2->getCoords()->getConstPointer();
8388   const double *cooBis=m1->getCoords()->getConstPointer();
8389   int offset2=offset1+m2->getNumberOfNodes();
8390   intersectEdge.resize(ncell);
8391   for(int i=0;i<ncell;i++,cI++)
8392     {
8393       const std::vector<int>& divs=subDiv[i];
8394       int nnode=cI[1]-cI[0]-1;
8395       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8396       std::map<INTERP_KERNEL::Node *, int> mapp22;
8397       for(int j=0;j<nnode;j++)
8398         {
8399           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8400           int nnid=c[(*cI)+j+1];
8401           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8402           mapp22[nn]=nnid+offset1;
8403         }
8404       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8405       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8406         ((*it).second.first)->decrRef();
8407       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8408       std::map<INTERP_KERNEL::Node *,int> mapp3;
8409       for(std::size_t j=0;j<divs.size();j++)
8410         {
8411           int id=divs[j];
8412           INTERP_KERNEL::Node *tmp=0;
8413           if(id<offset1)
8414             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8415           else if(id<offset2)
8416             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8417           else
8418             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8419           addNodes[j]=tmp;
8420           mapp3[tmp]=id;
8421         }
8422       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8423       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8424         (*it)->decrRef();
8425       e->decrRef();
8426     }
8427 }
8428
8429 /*!
8430  * 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).
8431  * 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
8432  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8433  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8434  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8435  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8436  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8437  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8438  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8439  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8440  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8441  * \param [out] cut3DSuf input/output param.
8442  */
8443 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8444                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8445                                                    const int *desc, const int *descIndx, 
8446                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8447 {
8448   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8449   int nbOf3DSurfCell=(int)cut3DSurf.size();
8450   for(int i=0;i<nbOf3DSurfCell;i++)
8451     {
8452       std::vector<int> res;
8453       int offset=descIndx[i];
8454       int nbOfSeg=descIndx[i+1]-offset;
8455       for(int j=0;j<nbOfSeg;j++)
8456         {
8457           int edgeId=desc[offset+j];
8458           int status=cut3DCurve[edgeId];
8459           if(status!=-2)
8460             {
8461               if(status>-1)
8462                 res.push_back(status);
8463               else
8464                 {
8465                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8466                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8467                 }
8468             }
8469         }
8470       switch(res.size())
8471         {
8472         case 2:
8473           {
8474             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8475             break;
8476           }
8477         case 1:
8478         case 0:
8479           {
8480             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8481             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8482             if(res.size()==2)
8483               {
8484                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8485               }
8486             else
8487               {
8488                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8489               }
8490             break;
8491           }
8492         default:
8493           {// case when plane is on a multi colinear edge of a polyhedron
8494             if((int)res.size()==2*nbOfSeg)
8495               {
8496                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8497               }
8498             else
8499               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8500           }
8501         }
8502     }
8503 }
8504
8505 /*!
8506  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8507  * 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).
8508  * 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
8509  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8510  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8511  * \param desc is the descending connectivity 3D->3DSurf
8512  * \param descIndx is the descending connectivity index 3D->3DSurf
8513  */
8514 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8515                                                   const int *desc, const int *descIndx,
8516                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8517 {
8518   checkFullyDefined();
8519   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8520     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8521   const int *nodal3D=_nodal_connec->getConstPointer();
8522   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8523   int nbOfCells=getNumberOfCells();
8524   for(int i=0;i<nbOfCells;i++)
8525     {
8526       std::map<int, std::set<int> > m;
8527       int offset=descIndx[i];
8528       int nbOfFaces=descIndx[i+1]-offset;
8529       int start=-1;
8530       int end=-1;
8531       for(int j=0;j<nbOfFaces;j++)
8532         {
8533           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8534           if(p.first!=-1 && p.second!=-1)
8535             {
8536               if(p.first!=-2)
8537                 {
8538                   start=p.first; end=p.second;
8539                   m[p.first].insert(p.second);
8540                   m[p.second].insert(p.first);
8541                 }
8542               else
8543                 {
8544                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8545                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8546                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8547                   INTERP_KERNEL::NormalizedCellType cmsId;
8548                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8549                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8550                   for(unsigned k=0;k<nbOfNodesSon;k++)
8551                     {
8552                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8553                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8554                     }
8555                 }
8556             }
8557         }
8558       if(m.empty())
8559         continue;
8560       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8561       int prev=end;
8562       while(end!=start)
8563         {
8564           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8565           const std::set<int>& s=(*it).second;
8566           std::set<int> s2; s2.insert(prev);
8567           std::set<int> s3;
8568           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8569           if(s3.size()==1)
8570             {
8571               int val=*s3.begin();
8572               conn.push_back(start);
8573               prev=start;
8574               start=val;
8575             }
8576           else
8577             start=end;
8578         }
8579       conn.push_back(end);
8580       if(conn.size()>3)
8581         {
8582           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8583           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8584           cellIds->pushBackSilent(i);
8585         }
8586     }
8587 }
8588
8589 /*!
8590  * 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
8591  * 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
8592  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8593  * 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
8594  * 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.
8595  * 
8596  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8597  */
8598 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8599 {
8600   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8601   if(sz>=4)
8602     {
8603       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8604       if(cm.getDimension()==2)
8605         {
8606           const int *node=nodalConnBg+1;
8607           int startNode=*node++;
8608           double refX=coords[2*startNode];
8609           for(;node!=nodalConnEnd;node++)
8610             {
8611               if(coords[2*(*node)]<refX)
8612                 {
8613                   startNode=*node;
8614                   refX=coords[2*startNode];
8615                 }
8616             }
8617           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8618           refX=1e300;
8619           double tmp1;
8620           double tmp2[2];
8621           double angle0=-M_PI/2;
8622           //
8623           int nextNode=-1;
8624           int prevNode=-1;
8625           double resRef;
8626           double angleNext=0.;
8627           while(nextNode!=startNode)
8628             {
8629               nextNode=-1;
8630               resRef=1e300;
8631               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8632                 {
8633                   if(*node!=tmpOut.back() && *node!=prevNode)
8634                     {
8635                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8636                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8637                       double res;
8638                       if(angleM<=angle0)
8639                         res=angle0-angleM;
8640                       else
8641                         res=angle0-angleM+2.*M_PI;
8642                       if(res<resRef)
8643                         {
8644                           nextNode=*node;
8645                           resRef=res;
8646                           angleNext=angleM;
8647                         }
8648                     }
8649                 }
8650               if(nextNode!=startNode)
8651                 {
8652                   angle0=angleNext-M_PI;
8653                   if(angle0<-M_PI)
8654                     angle0+=2*M_PI;
8655                   prevNode=tmpOut.back();
8656                   tmpOut.push_back(nextNode);
8657                 }
8658             }
8659           std::vector<int> tmp3(2*(sz-1));
8660           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8661           std::copy(nodalConnBg+1,nodalConnEnd,it);
8662           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8663             {
8664               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8665               return false;
8666             }
8667           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8668             {
8669               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8670               return false;
8671             }
8672           else
8673             {
8674               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8675               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8676               return true;
8677             }
8678         }
8679       else
8680         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8681     }
8682   else
8683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8684 }
8685
8686 /*!
8687  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8688  * 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.
8689  * 
8690  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8691  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8692  * \param [in,out] arr array in which the remove operation will be done.
8693  * \param [in,out] arrIndx array in the remove operation will modify
8694  * \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])
8695  * \return true if \b arr and \b arrIndx have been modified, false if not.
8696  */
8697 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8698 {
8699   if(!arrIndx || !arr)
8700     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8701   if(offsetForRemoval<0)
8702     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8703   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8704   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8705   int *arrIPtr=arrIndx->getPointer();
8706   *arrIPtr++=0;
8707   int previousArrI=0;
8708   const int *arrPtr=arr->getConstPointer();
8709   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8710   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8711     {
8712       if(*arrIPtr-previousArrI>offsetForRemoval)
8713         {
8714           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8715             {
8716               if(s.find(*work)==s.end())
8717                 arrOut.push_back(*work);
8718             }
8719         }
8720       previousArrI=*arrIPtr;
8721       *arrIPtr=(int)arrOut.size();
8722     }
8723   if(arr->getNumberOfTuples()==(int)arrOut.size())
8724     return false;
8725   arr->alloc((int)arrOut.size(),1);
8726   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8727   return true;
8728 }
8729
8730 /*!
8731  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8732  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8733  * The selection of extraction is done standardly in new2old format.
8734  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8735  *
8736  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8737  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8738  * \param [in] arrIn arr origin array from which the extraction will be done.
8739  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8740  * \param [out] arrOut the resulting array
8741  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8742  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8743  */
8744 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8745                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8746 {
8747   if(!arrIn || !arrIndxIn)
8748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8749   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8750   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8751     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8752   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8753   const int *arrInPtr=arrIn->getConstPointer();
8754   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8755   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8756   if(nbOfGrps<0)
8757     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8758   int maxSizeOfArr=arrIn->getNumberOfTuples();
8759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8761   arrIo->alloc((int)(sz+1),1);
8762   const int *idsIt=idsOfSelectBg;
8763   int *work=arrIo->getPointer();
8764   *work++=0;
8765   int lgth=0;
8766   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8767     {
8768       if(*idsIt>=0 && *idsIt<nbOfGrps)
8769         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8770       else
8771         {
8772           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8773           throw INTERP_KERNEL::Exception(oss.str().c_str());
8774         }
8775       if(lgth>=work[-1])
8776         *work=lgth;
8777       else
8778         {
8779           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8780           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8781           throw INTERP_KERNEL::Exception(oss.str().c_str());
8782         }
8783     }
8784   arro->alloc(lgth,1);
8785   work=arro->getPointer();
8786   idsIt=idsOfSelectBg;
8787   for(std::size_t i=0;i<sz;i++,idsIt++)
8788     {
8789       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8790         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8791       else
8792         {
8793           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8794           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8795           throw INTERP_KERNEL::Exception(oss.str().c_str());
8796         }
8797     }
8798   arrOut=arro.retn();
8799   arrIndexOut=arrIo.retn();
8800 }
8801
8802 /*!
8803  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8804  * 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 ).
8805  * The selection of extraction is done standardly in new2old format.
8806  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8807  *
8808  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8809  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8810  * \param [in] arrIn arr origin array from which the extraction will be done.
8811  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8812  * \param [out] arrOut the resulting array
8813  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8814  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8815  */
8816 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8817                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8818 {
8819   if(!arrIn || !arrIndxIn)
8820     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8821   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8822   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8823     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8824   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8825   const int *arrInPtr=arrIn->getConstPointer();
8826   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8827   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8828   if(nbOfGrps<0)
8829     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8830   int maxSizeOfArr=arrIn->getNumberOfTuples();
8831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8833   arrIo->alloc((int)(sz+1),1);
8834   int idsIt=idsOfSelectStart;
8835   int *work=arrIo->getPointer();
8836   *work++=0;
8837   int lgth=0;
8838   for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8839     {
8840       if(idsIt>=0 && idsIt<nbOfGrps)
8841         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8842       else
8843         {
8844           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8845           throw INTERP_KERNEL::Exception(oss.str().c_str());
8846         }
8847       if(lgth>=work[-1])
8848         *work=lgth;
8849       else
8850         {
8851           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8852           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8853           throw INTERP_KERNEL::Exception(oss.str().c_str());
8854         }
8855     }
8856   arro->alloc(lgth,1);
8857   work=arro->getPointer();
8858   idsIt=idsOfSelectStart;
8859   for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8860     {
8861       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8862         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8863       else
8864         {
8865           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8866           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8867           throw INTERP_KERNEL::Exception(oss.str().c_str());
8868         }
8869     }
8870   arrOut=arro.retn();
8871   arrIndexOut=arrIo.retn();
8872 }
8873
8874 /*!
8875  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8876  * 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
8877  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8878  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8879  *
8880  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8881  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8882  * \param [in] arrIn arr origin array from which the extraction will be done.
8883  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8884  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8885  * \param [in] srcArrIndex index array of \b srcArr
8886  * \param [out] arrOut the resulting array
8887  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8888  * 
8889  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8890  */
8891 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8892                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8893                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8894 {
8895   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8896     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8897   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8898   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8899   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8900   std::vector<bool> v(nbOfTuples,true);
8901   int offset=0;
8902   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8903   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8904   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8905     {
8906       if(*it>=0 && *it<nbOfTuples)
8907         {
8908           v[*it]=false;
8909           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8910         }
8911       else
8912         {
8913           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8914           throw INTERP_KERNEL::Exception(oss.str().c_str());
8915         }
8916     }
8917   srcArrIndexPtr=srcArrIndex->getConstPointer();
8918   arrIo->alloc(nbOfTuples+1,1);
8919   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8920   const int *arrInPtr=arrIn->getConstPointer();
8921   const int *srcArrPtr=srcArr->getConstPointer();
8922   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8923   int *arroPtr=arro->getPointer();
8924   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8925     {
8926       if(v[ii])
8927         {
8928           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8929           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8930         }
8931       else
8932         {
8933           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8934           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8935           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8936         }
8937     }
8938   arrOut=arro.retn();
8939   arrIndexOut=arrIo.retn();
8940 }
8941
8942 /*!
8943  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8944  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8945  *
8946  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8947  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8948  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8949  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8950  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8951  * \param [in] srcArrIndex index array of \b srcArr
8952  * 
8953  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8954  */
8955 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8956                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8957 {
8958   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8959     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8960   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8961   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8962   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8963   int *arrInOutPtr=arrInOut->getPointer();
8964   const int *srcArrPtr=srcArr->getConstPointer();
8965   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8966     {
8967       if(*it>=0 && *it<nbOfTuples)
8968         {
8969           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8970             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8971           else
8972             {
8973               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] !";
8974               throw INTERP_KERNEL::Exception(oss.str().c_str());
8975             }
8976         }
8977       else
8978         {
8979           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8980           throw INTERP_KERNEL::Exception(oss.str().c_str());
8981         }
8982     }
8983 }
8984
8985 /*!
8986  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8987  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8988  * 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]].
8989  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8990  * A negative value in \b arrIn means that it is ignored.
8991  * 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.
8992  * 
8993  * \param [in] arrIn arr origin array from which the extraction will be done.
8994  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8995  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8996  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8997  */
8998 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8999 {
9000   int seed=0,nbOfDepthPeelingPerformed=0;
9001   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9002 }
9003
9004 /*!
9005  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9006  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9007  * 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]].
9008  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9009  * A negative value in \b arrIn means that it is ignored.
9010  * 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.
9011  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9012  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9013  * \param [in] arrIn arr origin array from which the extraction will be done.
9014  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9015  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9016  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9017  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9018  * \sa MEDCouplingUMesh::partitionBySpreadZone
9019  */
9020 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9021 {
9022   nbOfDepthPeelingPerformed=0;
9023   if(!arrIndxIn)
9024     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9025   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9026   if(nbOfTuples<=0)
9027     {
9028       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9029       return ret;
9030     }
9031   //
9032   std::vector<bool> fetched(nbOfTuples,false);
9033   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9034 }
9035
9036 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)
9037 {
9038   nbOfDepthPeelingPerformed=0;
9039   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9040     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9041   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9042   std::vector<bool> fetched2(nbOfTuples,false);
9043   int i=0;
9044   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9045     {
9046       if(*seedElt>=0 && *seedElt<nbOfTuples)
9047         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9048       else
9049         { 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()); }
9050     }
9051   const int *arrInPtr=arrIn->getConstPointer();
9052   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9053   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9054   std::vector<int> idsToFetch1(seedBg,seedEnd);
9055   std::vector<int> idsToFetch2;
9056   std::vector<int> *idsToFetch=&idsToFetch1;
9057   std::vector<int> *idsToFetchOther=&idsToFetch2;
9058   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9059     {
9060       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9061         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9062           if(!fetched[*it2])
9063             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9064       std::swap(idsToFetch,idsToFetchOther);
9065       idsToFetchOther->clear();
9066       nbOfDepthPeelingPerformed++;
9067     }
9068   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9069   i=0;
9070   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9071   int *retPtr=ret->getPointer();
9072   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9073     if(*it)
9074       *retPtr++=i;
9075   return ret.retn();
9076 }
9077
9078 /*!
9079  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9080  * 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
9081  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9082  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9083  *
9084  * \param [in] start begin of set of ids of the input extraction (included)
9085  * \param [in] end end of set of ids of the input extraction (excluded)
9086  * \param [in] step step of the set of ids in range mode.
9087  * \param [in] arrIn arr origin array from which the extraction will be done.
9088  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9089  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9090  * \param [in] srcArrIndex index array of \b srcArr
9091  * \param [out] arrOut the resulting array
9092  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9093  * 
9094  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9095  */
9096 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9097                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9098                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9099 {
9100   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9101     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9102   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9104   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9105   int offset=0;
9106   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9107   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9108   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9109   int it=start;
9110   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9111     {
9112       if(it>=0 && it<nbOfTuples)
9113         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9114       else
9115         {
9116           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9117           throw INTERP_KERNEL::Exception(oss.str().c_str());
9118         }
9119     }
9120   srcArrIndexPtr=srcArrIndex->getConstPointer();
9121   arrIo->alloc(nbOfTuples+1,1);
9122   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9123   const int *arrInPtr=arrIn->getConstPointer();
9124   const int *srcArrPtr=srcArr->getConstPointer();
9125   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9126   int *arroPtr=arro->getPointer();
9127   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9128     {
9129       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9130       if(pos<0)
9131         {
9132           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9133           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9134         }
9135       else
9136         {
9137           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9138           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9139         }
9140     }
9141   arrOut=arro.retn();
9142   arrIndexOut=arrIo.retn();
9143 }
9144
9145 /*!
9146  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9147  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9148  *
9149  * \param [in] start begin of set of ids of the input extraction (included)
9150  * \param [in] end end of set of ids of the input extraction (excluded)
9151  * \param [in] step step of the set of ids in range mode.
9152  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9153  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9154  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9155  * \param [in] srcArrIndex index array of \b srcArr
9156  * 
9157  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9158  */
9159 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9160                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9161 {
9162   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9163     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9164   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9165   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9166   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9167   int *arrInOutPtr=arrInOut->getPointer();
9168   const int *srcArrPtr=srcArr->getConstPointer();
9169   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9170   int it=start;
9171   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9172     {
9173       if(it>=0 && it<nbOfTuples)
9174         {
9175           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9176             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9177           else
9178             {
9179               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9180               throw INTERP_KERNEL::Exception(oss.str().c_str());
9181             }
9182         }
9183       else
9184         {
9185           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9186           throw INTERP_KERNEL::Exception(oss.str().c_str());
9187         }
9188     }
9189 }
9190
9191 /*!
9192  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9193  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9194  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9195  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9196  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9197  * 
9198  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9199  */
9200 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9201 {
9202   checkFullyDefined();
9203   int mdim=getMeshDimension();
9204   int spaceDim=getSpaceDimension();
9205   if(mdim!=spaceDim)
9206     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9207   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9208   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9209   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9210   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9211   ret->setCoords(getCoords());
9212   ret->allocateCells((int)partition.size());
9213   //
9214   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9215     {
9216       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9217       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9218       switch(mdim)
9219         {
9220         case 2:
9221           cell=tmp->buildUnionOf2DMesh();
9222           break;
9223         case 3:
9224           cell=tmp->buildUnionOf3DMesh();
9225           break;
9226         default:
9227           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9228         }
9229       
9230       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9231     }
9232   //
9233   ret->finishInsertingCells();
9234   return ret.retn();
9235 }
9236
9237 /*!
9238  * This method partitions \b this into contiguous zone.
9239  * This method only needs a well defined connectivity. Coordinates are not considered here.
9240  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9241  */
9242 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9243 {
9244   int nbOfCellsCur=getNumberOfCells();
9245   std::vector<DataArrayInt *> ret;
9246   if(nbOfCellsCur<=0)
9247     return ret;
9248   DataArrayInt *neigh=0,*neighI=0;
9249   computeNeighborsOfCells(neigh,neighI);
9250   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9251   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9252   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9253   int seed=0;
9254   while(seed<nbOfCellsCur)
9255     {
9256       int nbOfPeelPerformed=0;
9257       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9258       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9259     }
9260   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9261     ret.push_back((*it).retn());
9262   return ret;
9263 }
9264
9265 /*!
9266  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9267  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9268  *
9269  * \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.
9270  * \return a newly allocated DataArrayInt to be managed by the caller.
9271  * \throw In case of \a code has not the right format (typically of size 3*n)
9272  */
9273 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9274 {
9275   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9276   std::size_t nb=code.size()/3;
9277   if(code.size()%3!=0)
9278     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9279   ret->alloc((int)nb,2);
9280   int *retPtr=ret->getPointer();
9281   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9282     {
9283       retPtr[0]=code[3*i+2];
9284       retPtr[1]=code[3*i+2]+code[3*i+1];
9285     }
9286   return ret.retn();
9287 }
9288
9289 /*!
9290  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9291  * All cells in \a this are expected to be linear 3D cells.
9292  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9293  * It leads to an increase to number of cells.
9294  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9295  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
9296  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9297  *
9298  * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells.
9299  *                      For all other cells, the splitting policy will be ignored.
9300  * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added. 
9301  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9302  *          an id of old cell producing it. The caller is to delete this array using
9303  *         decrRef() as it is no more needed.
9304  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9305  * 
9306  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9307  * \throw If \a this is not fully constituted with linear 3D cells.
9308  * \sa MEDCouplingUMesh::simplexize
9309  */
9310 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const throw(INTERP_KERNEL::Exception)
9311 {
9312   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9313   checkConnectivityFullyDefined();
9314   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9315     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9316   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9317   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
9318   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9319   int *retPt(ret->getPointer());
9320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9321   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9322   const int *oldc(_nodal_connec->begin());
9323   const int *oldci(_nodal_connec_index->begin());
9324   const double *coords(_coords->begin());
9325   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9326     {
9327       std::vector<int> a; std::vector<double> b;
9328       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9329       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9330       const int *aa(&a[0]);
9331       if(!b.empty())
9332         {
9333           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9334             if(*it<0)
9335               *it=(-(*(it))-1+nbNodes);
9336           addPts->insertAtTheEnd(b.begin(),b.end());
9337           nbNodes+=(int)b.size()/3;
9338         }
9339       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9340         newConn->insertAtTheEnd(aa,aa+4);
9341     }
9342   if(!addPts->empty())
9343     {
9344       addPts->rearrange(3);
9345       nbOfAdditionalPoints=addPts->getNumberOfTuples();
9346       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9347       ret0->setCoords(addPts);
9348     }
9349   else
9350     {
9351       nbOfAdditionalPoints=0;
9352       ret0->setCoords(getCoords());
9353     }
9354   ret0->setNodalConnectivity(newConn);
9355   //
9356   ret->computeOffsets2();
9357   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9358   return ret0.retn();
9359 }
9360
9361 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9362                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9363 {
9364   if(mesh)
9365     {
9366       mesh->incrRef();
9367       _nb_cell=mesh->getNumberOfCells();
9368     }
9369 }
9370
9371 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9372 {
9373   if(_mesh)
9374     _mesh->decrRef();
9375   if(_own_cell)
9376     delete _cell;
9377 }
9378
9379 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9380                                                                                                                                _own_cell(false),_cell_id(bg-1),
9381                                                                                                                                _nb_cell(end)
9382 {
9383   if(mesh)
9384     mesh->incrRef();
9385 }
9386
9387 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9388 {
9389   _cell_id++;
9390   if(_cell_id<_nb_cell)
9391     {
9392       _cell->next();
9393       return _cell;
9394     }
9395   else
9396     return 0;
9397 }
9398
9399 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9400 {
9401   if(_mesh)
9402     _mesh->incrRef();
9403 }
9404
9405 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9406 {
9407   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9408 }
9409
9410 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9411 {
9412   if(_mesh)
9413     _mesh->decrRef();
9414 }
9415
9416 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9417                                                                                                                                                                   _itc(itc),
9418                                                                                                                                                                   _bg(bg),_end(end)
9419 {
9420   if(_mesh)
9421     _mesh->incrRef();
9422 }
9423
9424 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9425 {
9426   if(_mesh)
9427     _mesh->decrRef();
9428 }
9429
9430 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9431 {
9432   return _type;
9433 }
9434
9435 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9436 {
9437   return _end-_bg;
9438 }
9439
9440 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9441 {
9442   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9443 }
9444
9445 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9446 {
9447   if(mesh)
9448     {
9449       mesh->incrRef();
9450       _nb_cell=mesh->getNumberOfCells();
9451     }
9452 }
9453
9454 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9455 {
9456   if(_mesh)
9457     _mesh->decrRef();
9458   delete _cell;
9459 }
9460
9461 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9462 {
9463   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9464   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9465   if(_cell_id<_nb_cell)
9466     {
9467       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9468       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9469       int startId=_cell_id;
9470       _cell_id+=nbOfElems;
9471       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9472     }
9473   else
9474     return 0;
9475 }
9476
9477 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9478 {
9479   if(mesh)
9480     {
9481       _conn=mesh->getNodalConnectivity()->getPointer();
9482       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9483     }
9484 }
9485
9486 void MEDCouplingUMeshCell::next()
9487 {
9488   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9489     {
9490       _conn+=_conn_lgth;
9491       _conn_indx++;
9492     }
9493   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9494 }
9495
9496 std::string MEDCouplingUMeshCell::repr() const
9497 {
9498   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9499     {
9500       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9501       oss << " : ";
9502       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9503       return oss.str();
9504     }
9505   else
9506     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9507 }
9508
9509 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9510 {
9511   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9512     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9513   else
9514     return INTERP_KERNEL::NORM_ERROR;
9515 }
9516
9517 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9518 {
9519   lgth=_conn_lgth;
9520   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9521     return _conn;
9522   else
9523     return 0;
9524 }