Salome HOME
MEDCouplingMesh::computeEffectiveNbOfNodesPerCell
[modules/med.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  */
5243 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5244 {
5245   switch(policy)
5246     {
5247     case 0:
5248       return simplexizePol0();
5249     case 1:
5250       return simplexizePol1();
5251     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5252       return simplexizePlanarFace5();
5253     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5254       return simplexizePlanarFace6();
5255     default:
5256       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)");
5257     }
5258 }
5259
5260 /*!
5261  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5262  * - 1D: INTERP_KERNEL::NORM_SEG2
5263  * - 2D: INTERP_KERNEL::NORM_TRI3
5264  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5265  *
5266  * This method is useful for users that need to use P1 field services as
5267  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5268  * All these methods need mesh support containing only simplex cells.
5269  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5270  *  \throw If the coordinates array is not set.
5271  *  \throw If the nodal connectivity of cells is not defined.
5272  *  \throw If \a this->getMeshDimension() < 1.
5273  */
5274 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5275 {
5276   checkFullyDefined();
5277   int mdim=getMeshDimension();
5278   if(mdim<1 || mdim>3)
5279     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5280   int nbCells=getNumberOfCells();
5281   const int *conn=_nodal_connec->getConstPointer();
5282   const int *connI=_nodal_connec_index->getConstPointer();
5283   for(int i=0;i<nbCells;i++)
5284     {
5285       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5286       if(!cm.isSimplex())
5287         return false;
5288     }
5289   return true;
5290 }
5291
5292 /*!
5293  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5294  */
5295 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5296 {
5297   checkConnectivityFullyDefined();
5298   if(getMeshDimension()!=2)
5299     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5300   int nbOfCells=getNumberOfCells();
5301   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5302   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5303   ret->alloc(nbOfCells+nbOfCutCells,1);
5304   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5305   int *retPt=ret->getPointer();
5306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5308   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5309   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5310   int *pt=newConn->getPointer();
5311   int *ptI=newConnI->getPointer();
5312   ptI[0]=0;
5313   const int *oldc=_nodal_connec->getConstPointer();
5314   const int *ci=_nodal_connec_index->getConstPointer();
5315   for(int i=0;i<nbOfCells;i++,ci++)
5316     {
5317       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5318         {
5319           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5320                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5321           pt=std::copy(tmp,tmp+8,pt);
5322           ptI[1]=ptI[0]+4;
5323           ptI[2]=ptI[0]+8;
5324           *retPt++=i;
5325           *retPt++=i;
5326           ptI+=2;
5327         }
5328       else
5329         {
5330           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5331           ptI[1]=ptI[0]+ci[1]-ci[0];
5332           ptI++;
5333           *retPt++=i;
5334         }
5335     }
5336   _nodal_connec->decrRef();
5337   _nodal_connec=newConn.retn();
5338   _nodal_connec_index->decrRef();
5339   _nodal_connec_index=newConnI.retn();
5340   computeTypes();
5341   updateTime();
5342   return ret.retn();
5343 }
5344
5345 /*!
5346  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5347  */
5348 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5349 {
5350   checkConnectivityFullyDefined();
5351   if(getMeshDimension()!=2)
5352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5353   int nbOfCells=getNumberOfCells();
5354   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5355   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5356   ret->alloc(nbOfCells+nbOfCutCells,1);
5357   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5358   int *retPt=ret->getPointer();
5359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5361   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5362   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5363   int *pt=newConn->getPointer();
5364   int *ptI=newConnI->getPointer();
5365   ptI[0]=0;
5366   const int *oldc=_nodal_connec->getConstPointer();
5367   const int *ci=_nodal_connec_index->getConstPointer();
5368   for(int i=0;i<nbOfCells;i++,ci++)
5369     {
5370       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5371         {
5372           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5373                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5374           pt=std::copy(tmp,tmp+8,pt);
5375           ptI[1]=ptI[0]+4;
5376           ptI[2]=ptI[0]+8;
5377           *retPt++=i;
5378           *retPt++=i;
5379           ptI+=2;
5380         }
5381       else
5382         {
5383           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5384           ptI[1]=ptI[0]+ci[1]-ci[0];
5385           ptI++;
5386           *retPt++=i;
5387         }
5388     }
5389   _nodal_connec->decrRef();
5390   _nodal_connec=newConn.retn();
5391   _nodal_connec_index->decrRef();
5392   _nodal_connec_index=newConnI.retn();
5393   computeTypes();
5394   updateTime();
5395   return ret.retn();
5396 }
5397
5398 /*!
5399  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5400  */
5401 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5402 {
5403   checkConnectivityFullyDefined();
5404   if(getMeshDimension()!=3)
5405     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5406   int nbOfCells=getNumberOfCells();
5407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5408   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5409   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5410   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5411   int *retPt=ret->getPointer();
5412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5414   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5415   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5416   int *pt=newConn->getPointer();
5417   int *ptI=newConnI->getPointer();
5418   ptI[0]=0;
5419   const int *oldc=_nodal_connec->getConstPointer();
5420   const int *ci=_nodal_connec_index->getConstPointer();
5421   for(int i=0;i<nbOfCells;i++,ci++)
5422     {
5423       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5424         {
5425           for(int j=0;j<5;j++,pt+=5,ptI++)
5426             {
5427               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5428               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];
5429               *retPt++=i;
5430               ptI[1]=ptI[0]+5;
5431             }
5432         }
5433       else
5434         {
5435           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5436           ptI[1]=ptI[0]+ci[1]-ci[0];
5437           ptI++;
5438           *retPt++=i;
5439         }
5440     }
5441   _nodal_connec->decrRef();
5442   _nodal_connec=newConn.retn();
5443   _nodal_connec_index->decrRef();
5444   _nodal_connec_index=newConnI.retn();
5445   computeTypes();
5446   updateTime();
5447   return ret.retn();
5448 }
5449
5450 /*!
5451  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5452  */
5453 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5454 {
5455   checkConnectivityFullyDefined();
5456   if(getMeshDimension()!=3)
5457     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5458   int nbOfCells=getNumberOfCells();
5459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5460   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5461   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5462   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5463   int *retPt=ret->getPointer();
5464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5466   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5467   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5468   int *pt=newConn->getPointer();
5469   int *ptI=newConnI->getPointer();
5470   ptI[0]=0;
5471   const int *oldc=_nodal_connec->getConstPointer();
5472   const int *ci=_nodal_connec_index->getConstPointer();
5473   for(int i=0;i<nbOfCells;i++,ci++)
5474     {
5475       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5476         {
5477           for(int j=0;j<6;j++,pt+=5,ptI++)
5478             {
5479               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5480               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];
5481               *retPt++=i;
5482               ptI[1]=ptI[0]+5;
5483             }
5484         }
5485       else
5486         {
5487           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5488           ptI[1]=ptI[0]+ci[1]-ci[0];
5489           ptI++;
5490           *retPt++=i;
5491         }
5492     }
5493   _nodal_connec->decrRef();
5494   _nodal_connec=newConn.retn();
5495   _nodal_connec_index->decrRef();
5496   _nodal_connec_index=newConnI.retn();
5497   computeTypes();
5498   updateTime();
5499   return ret.retn();
5500 }
5501
5502 /*!
5503  * 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.
5504  * This method completly ignore coordinates.
5505  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5506  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5507  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5508  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5509  */
5510 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5511 {
5512   checkFullyDefined();
5513   if(getMeshDimension()!=2)
5514     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5515   int nbOfCells=getNumberOfCells();
5516   int *connI=_nodal_connec_index->getPointer();
5517   int newConnLgth=0;
5518   for(int i=0;i<nbOfCells;i++,connI++)
5519     {
5520       int offset=descIndex[i];
5521       int nbOfEdges=descIndex[i+1]-offset;
5522       //
5523       bool ddirect=desc[offset+nbOfEdges-1]>0;
5524       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5525       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5526       for(int j=0;j<nbOfEdges;j++)
5527         {
5528           bool direct=desc[offset+j]>0;
5529           int edgeId=std::abs(desc[offset+j])-1;
5530           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5531             {
5532               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5533               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5534               int ref2=direct?id1:id2;
5535               if(ref==ref2)
5536                 {
5537                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5538                   newConnLgth+=nbOfSubNodes-1;
5539                   ref=direct?id2:id1;
5540                 }
5541               else
5542                 {
5543                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5544                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5545                 }
5546             }
5547           else
5548             {
5549               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5550             }
5551         }
5552       newConnLgth++;//+1 is for cell type
5553       connI[1]=newConnLgth;
5554     }
5555   //
5556   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5557   newConn->alloc(newConnLgth,1);
5558   int *work=newConn->getPointer();
5559   for(int i=0;i<nbOfCells;i++)
5560     {
5561       *work++=INTERP_KERNEL::NORM_POLYGON;
5562       int offset=descIndex[i];
5563       int nbOfEdges=descIndex[i+1]-offset;
5564       for(int j=0;j<nbOfEdges;j++)
5565         {
5566           bool direct=desc[offset+j]>0;
5567           int edgeId=std::abs(desc[offset+j])-1;
5568           if(direct)
5569             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5570           else
5571             {
5572               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5573               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5574               work=std::copy(it,it+nbOfSubNodes-1,work);
5575             }
5576         }
5577     }
5578   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5579   _types.clear();
5580   if(nbOfCells>0)
5581     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5582 }
5583
5584 /*!
5585  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5586  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5587  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5588  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5589  * so it can be useful to call mergeNodes() before calling this method.
5590  *  \throw If \a this->getMeshDimension() <= 1.
5591  *  \throw If the coordinates array is not set.
5592  *  \throw If the nodal connectivity of cells is not defined.
5593  */
5594 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5595 {
5596   checkFullyDefined();
5597   if(getMeshDimension()<=1)
5598     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5599   int nbOfCells=getNumberOfCells();
5600   if(nbOfCells<1)
5601     return ;
5602   int initMeshLgth=getMeshLength();
5603   int *conn=_nodal_connec->getPointer();
5604   int *index=_nodal_connec_index->getPointer();
5605   int posOfCurCell=0;
5606   int newPos=0;
5607   int lgthOfCurCell;
5608   for(int i=0;i<nbOfCells;i++)
5609     {
5610       lgthOfCurCell=index[i+1]-posOfCurCell;
5611       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5612       int newLgth;
5613       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5614                                                                                                      conn+newPos+1,newLgth);
5615       conn[newPos]=newType;
5616       newPos+=newLgth+1;
5617       posOfCurCell=index[i+1];
5618       index[i+1]=newPos;
5619     }
5620   if(newPos!=initMeshLgth)
5621     _nodal_connec->reAlloc(newPos);
5622   computeTypes();
5623 }
5624
5625 /*!
5626  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5627  * A cell is considered to be oriented correctly if an angle between its
5628  * normal vector and a given vector is less than \c PI / \c 2.
5629  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5630  *         cells. 
5631  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5632  *         checked.
5633  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5634  *         is not cleared before filling in.
5635  *  \throw If \a this->getMeshDimension() != 2.
5636  *  \throw If \a this->getSpaceDimension() != 3.
5637  *
5638  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5639  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5640  */
5641 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5642 {
5643   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5644     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5645   int nbOfCells=getNumberOfCells();
5646   const int *conn=_nodal_connec->getConstPointer();
5647   const int *connI=_nodal_connec_index->getConstPointer();
5648   const double *coordsPtr=_coords->getConstPointer();
5649   for(int i=0;i<nbOfCells;i++)
5650     {
5651       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5652       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5653         {
5654           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5655           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5656             cells.push_back(i);
5657         }
5658     }
5659 }
5660
5661 /*!
5662  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5663  * considered to be oriented correctly if an angle between its normal vector and a
5664  * given vector is less than \c PI / \c 2. 
5665  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5666  *         cells. 
5667  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5668  *         checked.
5669  *  \throw If \a this->getMeshDimension() != 2.
5670  *  \throw If \a this->getSpaceDimension() != 3.
5671  *
5672  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5673  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5674  */
5675 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5676 {
5677   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5678     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5679   int nbOfCells=getNumberOfCells();
5680   int *conn=_nodal_connec->getPointer();
5681   const int *connI=_nodal_connec_index->getConstPointer();
5682   const double *coordsPtr=_coords->getConstPointer();
5683   bool isModified=false;
5684   for(int i=0;i<nbOfCells;i++)
5685     {
5686       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5687       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5688         {
5689           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5690           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5691             {
5692               isModified=true;
5693               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5694               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5695               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5696             }
5697         }
5698     }
5699   if(isModified)
5700     _nodal_connec->declareAsNew();
5701   updateTime();
5702 }
5703
5704 /*!
5705  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5706  * oriented facets. The normal vector of the facet should point out of the cell.
5707  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5708  *         is not cleared before filling in.
5709  *  \throw If \a this->getMeshDimension() != 3.
5710  *  \throw If \a this->getSpaceDimension() != 3.
5711  *  \throw If the coordinates array is not set.
5712  *  \throw If the nodal connectivity of cells is not defined.
5713  *
5714  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5715  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5716  */
5717 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5718 {
5719   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5720     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5721   int nbOfCells=getNumberOfCells();
5722   const int *conn=_nodal_connec->getConstPointer();
5723   const int *connI=_nodal_connec_index->getConstPointer();
5724   const double *coordsPtr=_coords->getConstPointer();
5725   for(int i=0;i<nbOfCells;i++)
5726     {
5727       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5728       if(type==INTERP_KERNEL::NORM_POLYHED)
5729         {
5730           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5731             cells.push_back(i);
5732         }
5733     }
5734 }
5735
5736 /*!
5737  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5738  * out of the cell. 
5739  *  \throw If \a this->getMeshDimension() != 3.
5740  *  \throw If \a this->getSpaceDimension() != 3.
5741  *  \throw If the coordinates array is not set.
5742  *  \throw If the nodal connectivity of cells is not defined.
5743  *  \throw If the reparation fails.
5744  *
5745  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5746  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5747  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5748  */
5749 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5750 {
5751   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5752     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5753   int nbOfCells=getNumberOfCells();
5754   int *conn=_nodal_connec->getPointer();
5755   const int *connI=_nodal_connec_index->getConstPointer();
5756   const double *coordsPtr=_coords->getConstPointer();
5757   for(int i=0;i<nbOfCells;i++)
5758     {
5759       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5760       if(type==INTERP_KERNEL::NORM_POLYHED)
5761         {
5762           try
5763             {
5764               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5765                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5766             }
5767           catch(INTERP_KERNEL::Exception& e)
5768             {
5769               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5770               throw INTERP_KERNEL::Exception(oss.str().c_str());
5771             }
5772         }
5773     }
5774   updateTime();
5775 }
5776
5777 /*!
5778  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5779  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5780  * according to which the first facet of the cell should be oriented to have the normal vector
5781  * pointing out of cell.
5782  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5783  *         cells. The caller is to delete this array using decrRef() as it is no more
5784  *         needed. 
5785  *  \throw If \a this->getMeshDimension() != 3.
5786  *  \throw If \a this->getSpaceDimension() != 3.
5787  *  \throw If the coordinates array is not set.
5788  *  \throw If the nodal connectivity of cells is not defined.
5789  *
5790  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5791  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5792  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5793  */
5794 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5795 {
5796   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5797   if(getMeshDimension()!=3)
5798     throw INTERP_KERNEL::Exception(msg);
5799   int spaceDim=getSpaceDimension();
5800   if(spaceDim!=3)
5801     throw INTERP_KERNEL::Exception(msg);
5802   //
5803   int nbOfCells=getNumberOfCells();
5804   int *conn=_nodal_connec->getPointer();
5805   const int *connI=_nodal_connec_index->getConstPointer();
5806   const double *coo=getCoords()->getConstPointer();
5807   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5808   for(int i=0;i<nbOfCells;i++)
5809     {
5810       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5811       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5812         {
5813           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5814             {
5815               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5816               cells->pushBackSilent(i);
5817             }
5818         }
5819     }
5820   return cells.retn();
5821 }
5822
5823 /*!
5824  * This method is a faster method to correct orientation of all 3D cells in \a this.
5825  * 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.
5826  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5827  * 
5828  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5829  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5830  */
5831 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5832 {
5833   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5834     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5835   int nbOfCells=getNumberOfCells();
5836   int *conn=_nodal_connec->getPointer();
5837   const int *connI=_nodal_connec_index->getConstPointer();
5838   const double *coordsPtr=_coords->getConstPointer();
5839   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5840   for(int i=0;i<nbOfCells;i++)
5841     {
5842       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5843       switch(type)
5844         {
5845         case INTERP_KERNEL::NORM_TETRA4:
5846           {
5847             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5848               {
5849                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5850                 ret->pushBackSilent(i);
5851               }
5852             break;
5853           }
5854         case INTERP_KERNEL::NORM_PYRA5:
5855           {
5856             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5857               {
5858                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5859                 ret->pushBackSilent(i);
5860               }
5861             break;
5862           }
5863         case INTERP_KERNEL::NORM_PENTA6:
5864         case INTERP_KERNEL::NORM_HEXA8:
5865         case INTERP_KERNEL::NORM_HEXGP12:
5866           {
5867             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5868               {
5869                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5870                 ret->pushBackSilent(i);
5871               }
5872             break;
5873           }
5874         case INTERP_KERNEL::NORM_POLYHED:
5875           {
5876             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5877               {
5878                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5879                 ret->pushBackSilent(i);
5880               }
5881             break;
5882           }
5883         default:
5884           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 !");
5885         }
5886     }
5887   updateTime();
5888   return ret.retn();
5889 }
5890
5891 /*!
5892  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5893  * If it is not the case an exception will be thrown.
5894  * This method is fast because the first cell of \a this is used to compute the plane.
5895  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5896  * \param pos output of size at least 3 used to store a point owned of searched plane.
5897  */
5898 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5899 {
5900   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5901     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5902   const int *conn=_nodal_connec->getConstPointer();
5903   const int *connI=_nodal_connec_index->getConstPointer();
5904   const double *coordsPtr=_coords->getConstPointer();
5905   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5906   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5907 }
5908
5909 /*!
5910  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5911  * cells. Currently cells of the following types are treated:
5912  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5913  * For a cell of other type an exception is thrown.
5914  * Space dimension of a 2D mesh can be either 2 or 3.
5915  * The Edge Ratio of a cell \f$t\f$ is: 
5916  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5917  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5918  *  the smallest edge lengths of \f$t\f$.
5919  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5920  *          cells and one time, lying on \a this mesh. The caller is to delete this
5921  *          field using decrRef() as it is no more needed. 
5922  *  \throw If the coordinates array is not set.
5923  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5924  *  \throw If the connectivity data array has more than one component.
5925  *  \throw If the connectivity data array has a named component.
5926  *  \throw If the connectivity index data array has more than one component.
5927  *  \throw If the connectivity index data array has a named component.
5928  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5929  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5930  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5931  */
5932 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5933 {
5934   checkCoherency();
5935   int spaceDim=getSpaceDimension();
5936   int meshDim=getMeshDimension();
5937   if(spaceDim!=2 && spaceDim!=3)
5938     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5939   if(meshDim!=2 && meshDim!=3)
5940     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5941   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5942   ret->setMesh(this);
5943   int nbOfCells=getNumberOfCells();
5944   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5945   arr->alloc(nbOfCells,1);
5946   double *pt=arr->getPointer();
5947   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5948   const int *conn=_nodal_connec->getConstPointer();
5949   const int *connI=_nodal_connec_index->getConstPointer();
5950   const double *coo=_coords->getConstPointer();
5951   double tmp[12];
5952   for(int i=0;i<nbOfCells;i++,pt++)
5953     {
5954       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5955       switch(t)
5956         {
5957           case INTERP_KERNEL::NORM_TRI3:
5958             {
5959               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5960               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5961               break;
5962             }
5963           case INTERP_KERNEL::NORM_QUAD4:
5964             {
5965               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5966               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5967               break;
5968             }
5969           case INTERP_KERNEL::NORM_TETRA4:
5970             {
5971               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5972               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5973               break;
5974             }
5975         default:
5976           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5977         }
5978       conn+=connI[i+1]-connI[i];
5979     }
5980   ret->setName("EdgeRatio");
5981   ret->synchronizeTimeWithSupport();
5982   return ret.retn();
5983 }
5984
5985 /*!
5986  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5987  * cells. Currently cells of the following types are treated:
5988  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5989  * For a cell of other type an exception is thrown.
5990  * Space dimension of a 2D mesh can be either 2 or 3.
5991  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5992  *          cells and one time, lying on \a this mesh. The caller is to delete this
5993  *          field using decrRef() as it is no more needed. 
5994  *  \throw If the coordinates array is not set.
5995  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5996  *  \throw If the connectivity data array has more than one component.
5997  *  \throw If the connectivity data array has a named component.
5998  *  \throw If the connectivity index data array has more than one component.
5999  *  \throw If the connectivity index data array has a named component.
6000  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6001  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6002  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6003  */
6004 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6005 {
6006   checkCoherency();
6007   int spaceDim=getSpaceDimension();
6008   int meshDim=getMeshDimension();
6009   if(spaceDim!=2 && spaceDim!=3)
6010     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6011   if(meshDim!=2 && meshDim!=3)
6012     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6013   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6014   ret->setMesh(this);
6015   int nbOfCells=getNumberOfCells();
6016   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6017   arr->alloc(nbOfCells,1);
6018   double *pt=arr->getPointer();
6019   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6020   const int *conn=_nodal_connec->getConstPointer();
6021   const int *connI=_nodal_connec_index->getConstPointer();
6022   const double *coo=_coords->getConstPointer();
6023   double tmp[12];
6024   for(int i=0;i<nbOfCells;i++,pt++)
6025     {
6026       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6027       switch(t)
6028         {
6029           case INTERP_KERNEL::NORM_TRI3:
6030             {
6031               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6032               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6033               break;
6034             }
6035           case INTERP_KERNEL::NORM_QUAD4:
6036             {
6037               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6038               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6039               break;
6040             }
6041           case INTERP_KERNEL::NORM_TETRA4:
6042             {
6043               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6044               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6045               break;
6046             }
6047         default:
6048           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6049         }
6050       conn+=connI[i+1]-connI[i];
6051     }
6052   ret->setName("AspectRatio");
6053   ret->synchronizeTimeWithSupport();
6054   return ret.retn();
6055 }
6056
6057 /*!
6058  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6059  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6060  * treated: INTERP_KERNEL::NORM_QUAD4.
6061  * For a cell of other type an exception is thrown.
6062  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6063  *          cells and one time, lying on \a this mesh. The caller is to delete this
6064  *          field using decrRef() as it is no more needed. 
6065  *  \throw If the coordinates array is not set.
6066  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6067  *  \throw If the connectivity data array has more than one component.
6068  *  \throw If the connectivity data array has a named component.
6069  *  \throw If the connectivity index data array has more than one component.
6070  *  \throw If the connectivity index data array has a named component.
6071  *  \throw If \a this->getMeshDimension() != 2.
6072  *  \throw If \a this->getSpaceDimension() != 3.
6073  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6074  */
6075 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6076 {
6077   checkCoherency();
6078   int spaceDim=getSpaceDimension();
6079   int meshDim=getMeshDimension();
6080   if(spaceDim!=3)
6081     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6082   if(meshDim!=2)
6083     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6084   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6085   ret->setMesh(this);
6086   int nbOfCells=getNumberOfCells();
6087   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6088   arr->alloc(nbOfCells,1);
6089   double *pt=arr->getPointer();
6090   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6091   const int *conn=_nodal_connec->getConstPointer();
6092   const int *connI=_nodal_connec_index->getConstPointer();
6093   const double *coo=_coords->getConstPointer();
6094   double tmp[12];
6095   for(int i=0;i<nbOfCells;i++,pt++)
6096     {
6097       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6098       switch(t)
6099         {
6100           case INTERP_KERNEL::NORM_QUAD4:
6101             {
6102               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6103               *pt=INTERP_KERNEL::quadWarp(tmp);
6104               break;
6105             }
6106         default:
6107           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6108         }
6109       conn+=connI[i+1]-connI[i];
6110     }
6111   ret->setName("Warp");
6112   ret->synchronizeTimeWithSupport();
6113   return ret.retn();
6114 }
6115
6116
6117 /*!
6118  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6119  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6120  * treated: INTERP_KERNEL::NORM_QUAD4.
6121  * For a cell of other type an exception is thrown.
6122  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6123  *          cells and one time, lying on \a this mesh. The caller is to delete this
6124  *          field using decrRef() as it is no more needed. 
6125  *  \throw If the coordinates array is not set.
6126  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6127  *  \throw If the connectivity data array has more than one component.
6128  *  \throw If the connectivity data array has a named component.
6129  *  \throw If the connectivity index data array has more than one component.
6130  *  \throw If the connectivity index data array has a named component.
6131  *  \throw If \a this->getMeshDimension() != 2.
6132  *  \throw If \a this->getSpaceDimension() != 3.
6133  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6134  */
6135 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6136 {
6137   checkCoherency();
6138   int spaceDim=getSpaceDimension();
6139   int meshDim=getMeshDimension();
6140   if(spaceDim!=3)
6141     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6142   if(meshDim!=2)
6143     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6144   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6145   ret->setMesh(this);
6146   int nbOfCells=getNumberOfCells();
6147   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6148   arr->alloc(nbOfCells,1);
6149   double *pt=arr->getPointer();
6150   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6151   const int *conn=_nodal_connec->getConstPointer();
6152   const int *connI=_nodal_connec_index->getConstPointer();
6153   const double *coo=_coords->getConstPointer();
6154   double tmp[12];
6155   for(int i=0;i<nbOfCells;i++,pt++)
6156     {
6157       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6158       switch(t)
6159         {
6160           case INTERP_KERNEL::NORM_QUAD4:
6161             {
6162               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6163               *pt=INTERP_KERNEL::quadSkew(tmp);
6164               break;
6165             }
6166         default:
6167           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6168         }
6169       conn+=connI[i+1]-connI[i];
6170     }
6171   ret->setName("Skew");
6172   ret->synchronizeTimeWithSupport();
6173   return ret.retn();
6174 }
6175
6176 /*!
6177  * This method aggregate the bbox of each cell and put it into bbox parameter.
6178  * \param bbox out parameter of size 2*spacedim*nbOfcells.
6179  */
6180 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6181 {
6182   int spaceDim=getSpaceDimension();
6183   int nbOfCells=getNumberOfCells();
6184   bbox.resize(2*nbOfCells*spaceDim);
6185   for(int i=0;i<nbOfCells*spaceDim;i++)
6186     {
6187       bbox[2*i]=std::numeric_limits<double>::max();
6188       bbox[2*i+1]=-std::numeric_limits<double>::max();
6189     }
6190   const double *coordsPtr=_coords->getConstPointer();
6191   const int *conn=_nodal_connec->getConstPointer();
6192   const int *connI=_nodal_connec_index->getConstPointer();
6193   for(int i=0;i<nbOfCells;i++)
6194     {
6195       int offset=connI[i]+1;
6196       int nbOfNodesForCell=connI[i+1]-offset;
6197       for(int j=0;j<nbOfNodesForCell;j++)
6198         {
6199           int nodeId=conn[offset+j];
6200           if(nodeId>=0)
6201             for(int k=0;k<spaceDim;k++)
6202               {
6203                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6204                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6205               }
6206         }
6207     }
6208 }
6209
6210 /// @cond INTERNAL
6211
6212 namespace ParaMEDMEMImpl
6213 {
6214   class ConnReader
6215   {
6216   public:
6217     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6218     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6219   private:
6220     const int *_conn;
6221     int _val;
6222   };
6223
6224   class ConnReader2
6225   {
6226   public:
6227     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6228     bool operator() (const int& pos) { return _conn[pos]==_val; }
6229   private:
6230     const int *_conn;
6231     int _val;
6232   };
6233 }
6234
6235 /// @endcond
6236
6237 /*!
6238  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6239  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6240  * \a this is composed in cell types.
6241  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6242  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6243  * This parameter is kept only for compatibility with other methode listed above.
6244  */
6245 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6246 {
6247   checkConnectivityFullyDefined();
6248   const int *conn=_nodal_connec->getConstPointer();
6249   const int *connI=_nodal_connec_index->getConstPointer();
6250   const int *work=connI;
6251   int nbOfCells=getNumberOfCells();
6252   std::size_t n=getAllTypes().size();
6253   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6254   std::set<INTERP_KERNEL::NormalizedCellType> types;
6255   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6256     {
6257       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6258       if(types.find(typ)!=types.end())
6259         {
6260           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6261           oss << " is not contiguous !";
6262           throw INTERP_KERNEL::Exception(oss.str().c_str());
6263         }
6264       types.insert(typ);
6265       ret[3*i]=typ;
6266       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6267       ret[3*i+1]=(int)std::distance(work,work2);
6268       work=work2;
6269     }
6270   return ret;
6271 }
6272
6273 /*!
6274  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6275  * only for types cell, type node is not managed.
6276  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6277  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6278  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6279  * If 2 or more same geometric type is in \a code and exception is thrown too.
6280  *
6281  * This method firstly checks
6282  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6283  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6284  * an exception is thrown too.
6285  * 
6286  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6287  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6288  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6289  */
6290 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6291 {
6292   if(code.empty())
6293     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6294   std::size_t sz=code.size();
6295   std::size_t n=sz/3;
6296   if(sz%3!=0)
6297     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6298   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6299   int nb=0;
6300   bool isNoPflUsed=true;
6301   for(std::size_t i=0;i<n;i++)
6302     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6303       {
6304         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6305         nb+=code[3*i+1];
6306         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6307           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6308         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6309       }
6310   if(types.size()!=n)
6311     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6312   if(isNoPflUsed)
6313     {
6314       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6315         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6316       if(types.size()==_types.size())
6317         return 0;
6318     }
6319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6320   ret->alloc(nb,1);
6321   int *retPtr=ret->getPointer();
6322   const int *connI=_nodal_connec_index->getConstPointer();
6323   const int *conn=_nodal_connec->getConstPointer();
6324   int nbOfCells=getNumberOfCells();
6325   const int *i=connI;
6326   int kk=0;
6327   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6328     {
6329       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6330       int offset=(int)std::distance(connI,i);
6331       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6332       int nbOfCellsOfCurType=(int)std::distance(i,j);
6333       if(code[3*kk+2]==-1)
6334         for(int k=0;k<nbOfCellsOfCurType;k++)
6335           *retPtr++=k+offset;
6336       else
6337         {
6338           int idInIdsPerType=code[3*kk+2];
6339           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6340             {
6341               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6342               if(zePfl)
6343                 {
6344                   zePfl->checkAllocated();
6345                   if(zePfl->getNumberOfComponents()==1)
6346                     {
6347                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6348                         {
6349                           if(*k>=0 && *k<nbOfCellsOfCurType)
6350                             *retPtr=(*k)+offset;
6351                           else
6352                             {
6353                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6354                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6355                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6356                             }
6357                         }
6358                     }
6359                   else
6360                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6361                 }
6362               else
6363                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6364             }
6365           else
6366             {
6367               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6368               oss << " should be in [0," << idsPerType.size() << ") !";
6369               throw INTERP_KERNEL::Exception(oss.str().c_str());
6370             }
6371         }
6372       i=j;
6373     }
6374   return ret.retn();
6375 }
6376
6377 /*!
6378  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6379  * 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.
6380  * 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.
6381  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6382  * 
6383  * \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.
6384  * \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,
6385  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6386  * \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.
6387  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6388  * \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
6389  */
6390 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6391 {
6392   if(!profile)
6393     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6394   if(profile->getNumberOfComponents()!=1)
6395     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6396   checkConnectivityFullyDefined();
6397   const int *conn=_nodal_connec->getConstPointer();
6398   const int *connI=_nodal_connec_index->getConstPointer();
6399   int nbOfCells=getNumberOfCells();
6400   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6401   std::vector<int> typeRangeVals(1);
6402   for(const int *i=connI;i!=connI+nbOfCells;)
6403     {
6404       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6405       if(std::find(types.begin(),types.end(),curType)!=types.end())
6406         {
6407           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6408         }
6409       types.push_back(curType);
6410       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6411       typeRangeVals.push_back((int)std::distance(connI,i));
6412     }
6413   //
6414   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6415   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6416   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6417   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6419   //
6420   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6421   code.resize(3*nbOfCastsFinal);
6422   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6423   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6424   for(int i=0;i<nbOfCastsFinal;i++)
6425     {
6426       int castId=castsPresent->getIJ(i,0);
6427       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6428       idsInPflPerType2.push_back(tmp3);
6429       code[3*i]=(int)types[castId];
6430       code[3*i+1]=tmp3->getNumberOfTuples();
6431       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6432       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6433         {
6434           tmp4->copyStringInfoFrom(*profile);
6435           idsPerType2.push_back(tmp4);
6436           code[3*i+2]=(int)idsPerType2.size()-1;
6437         }
6438       else
6439         {
6440           code[3*i+2]=-1;
6441         }
6442     }
6443   std::size_t sz2=idsInPflPerType2.size();
6444   idsInPflPerType.resize(sz2);
6445   for(std::size_t i=0;i<sz2;i++)
6446     {
6447       DataArrayInt *locDa=idsInPflPerType2[i];
6448       locDa->incrRef();
6449       idsInPflPerType[i]=locDa;
6450     }
6451   std::size_t sz=idsPerType2.size();
6452   idsPerType.resize(sz);
6453   for(std::size_t i=0;i<sz;i++)
6454     {
6455       DataArrayInt *locDa=idsPerType2[i];
6456       locDa->incrRef();
6457       idsPerType[i]=locDa;
6458     }
6459 }
6460
6461 /*!
6462  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6463  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6464  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6465  * 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.
6466  */
6467 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6468 {
6469   checkFullyDefined();
6470   nM1LevMesh->checkFullyDefined();
6471   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6472     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6473   if(_coords!=nM1LevMesh->getCoords())
6474     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6475   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6476   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6477   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6478   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6479   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6480   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6481   tmp->setConnectivity(tmp0,tmp1);
6482   tmp->renumberCells(ret0->getConstPointer(),false);
6483   revDesc=tmp->getNodalConnectivity();
6484   revDescIndx=tmp->getNodalConnectivityIndex();
6485   DataArrayInt *ret=0;
6486   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6487     {
6488       int tmp2;
6489       ret->getMaxValue(tmp2);
6490       ret->decrRef();
6491       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6492       throw INTERP_KERNEL::Exception(oss.str().c_str());
6493     }
6494   nM1LevMeshIds=ret;
6495   //
6496   revDesc->incrRef();
6497   revDescIndx->incrRef();
6498   ret1->incrRef();
6499   ret0->incrRef();
6500   meshnM1Old2New=ret0;
6501   return ret1;
6502 }
6503
6504 /*!
6505  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6506  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6507  * in "Old to New" mode.
6508  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6509  *          this array using decrRef() as it is no more needed.
6510  *  \throw If the nodal connectivity of cells is not defined.
6511  */
6512 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6513 {
6514   checkConnectivityFullyDefined();
6515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6516   renumberCells(ret->getConstPointer(),false);
6517   return ret.retn();
6518 }
6519
6520 /*!
6521  * This methods checks that cells are sorted by their types.
6522  * This method makes asumption (no check) that connectivity is correctly set before calling.
6523  */
6524 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6525 {
6526   checkFullyDefined();
6527   const int *conn=_nodal_connec->getConstPointer();
6528   const int *connI=_nodal_connec_index->getConstPointer();
6529   int nbOfCells=getNumberOfCells();
6530   std::set<INTERP_KERNEL::NormalizedCellType> types;
6531   for(const int *i=connI;i!=connI+nbOfCells;)
6532     {
6533       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6534       if(types.find(curType)!=types.end())
6535         return false;
6536       types.insert(curType);
6537       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6538     }
6539   return true;
6540 }
6541
6542 /*!
6543  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6544  * The geometric type order is specified by MED file.
6545  * 
6546  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6547  */
6548 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6549 {
6550   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6551 }
6552
6553 /*!
6554  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6555  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6556  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6557  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6558  */
6559 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6560 {
6561   checkFullyDefined();
6562   const int *conn=_nodal_connec->getConstPointer();
6563   const int *connI=_nodal_connec_index->getConstPointer();
6564   int nbOfCells=getNumberOfCells();
6565   if(nbOfCells==0)
6566     return true;
6567   int lastPos=-1;
6568   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6569   for(const int *i=connI;i!=connI+nbOfCells;)
6570     {
6571       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6572       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6573       if(isTypeExists!=orderEnd)
6574         {
6575           int pos=(int)std::distance(orderBg,isTypeExists);
6576           if(pos<=lastPos)
6577             return false;
6578           lastPos=pos;
6579           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6580         }
6581       else
6582         {
6583           if(sg.find(curType)==sg.end())
6584             {
6585               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6586               sg.insert(curType);
6587             }
6588           else
6589             return false;
6590         }
6591     }
6592   return true;
6593 }
6594
6595 /*!
6596  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6597  * 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
6598  * 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'.
6599  */
6600 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6601 {
6602   checkConnectivityFullyDefined();
6603   int nbOfCells=getNumberOfCells();
6604   const int *conn=_nodal_connec->getConstPointer();
6605   const int *connI=_nodal_connec_index->getConstPointer();
6606   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6607   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6608   tmpa->alloc(nbOfCells,1);
6609   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6610   tmpb->fillWithZero();
6611   int *tmp=tmpa->getPointer();
6612   int *tmp2=tmpb->getPointer();
6613   for(const int *i=connI;i!=connI+nbOfCells;i++)
6614     {
6615       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6616       if(where!=orderEnd)
6617         {
6618           int pos=(int)std::distance(orderBg,where);
6619           tmp2[pos]++;
6620           tmp[std::distance(connI,i)]=pos;
6621         }
6622       else
6623         {
6624           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6625           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6626           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6627           throw INTERP_KERNEL::Exception(oss.str().c_str());
6628         }
6629     }
6630   nbPerType=tmpb.retn();
6631   return tmpa.retn();
6632 }
6633
6634 /*!
6635  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6636  *
6637  * \return a new object containing the old to new correspondance.
6638  *
6639  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6640  */
6641 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6642 {
6643   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6644 }
6645
6646 /*!
6647  * 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.
6648  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6649  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6650  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6651  */
6652 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6653 {
6654   DataArrayInt *nbPerType=0;
6655   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6656   nbPerType->decrRef();
6657   return tmpa->buildPermArrPerLevel();
6658 }
6659
6660 /*!
6661  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6662  * The number of cells remains unchanged after the call of this method.
6663  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6664  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6665  *
6666  * \return the array giving the correspondance old to new.
6667  */
6668 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6669 {
6670   checkFullyDefined();
6671   computeTypes();
6672   const int *conn=_nodal_connec->getConstPointer();
6673   const int *connI=_nodal_connec_index->getConstPointer();
6674   int nbOfCells=getNumberOfCells();
6675   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6676   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6677     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6678       {
6679         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6680         types.push_back(curType);
6681         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6682       }
6683   DataArrayInt *ret=DataArrayInt::New();
6684   ret->alloc(nbOfCells,1);
6685   int *retPtr=ret->getPointer();
6686   std::fill(retPtr,retPtr+nbOfCells,-1);
6687   int newCellId=0;
6688   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6689     {
6690       for(const int *i=connI;i!=connI+nbOfCells;i++)
6691         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6692           retPtr[std::distance(connI,i)]=newCellId++;
6693     }
6694   renumberCells(retPtr,false);
6695   return ret;
6696 }
6697
6698 /*!
6699  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6700  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6701  * This method makes asumption that connectivity is correctly set before calling.
6702  */
6703 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6704 {
6705   checkConnectivityFullyDefined();
6706   const int *conn=_nodal_connec->getConstPointer();
6707   const int *connI=_nodal_connec_index->getConstPointer();
6708   int nbOfCells=getNumberOfCells();
6709   std::vector<MEDCouplingUMesh *> ret;
6710   for(const int *i=connI;i!=connI+nbOfCells;)
6711     {
6712       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6713       int beginCellId=(int)std::distance(connI,i);
6714       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6715       int endCellId=(int)std::distance(connI,i);
6716       int sz=endCellId-beginCellId;
6717       int *cells=new int[sz];
6718       for(int j=0;j<sz;j++)
6719         cells[j]=beginCellId+j;
6720       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6721       delete [] cells;
6722       ret.push_back(m);
6723     }
6724   return ret;
6725 }
6726
6727 /*!
6728  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6729  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6730  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6731  *
6732  * \return a newly allocated instance, that the caller must manage.
6733  * \throw If \a this contains more than one geometric type.
6734  * \throw If the nodal connectivity of \a this is not fully defined.
6735  * \throw If the internal data is not coherent.
6736  */
6737 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6738 {
6739   checkConnectivityFullyDefined();
6740     if(_types.size()!=1)
6741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6742   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6743   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6744   ret->setCoords(getCoords());
6745   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6746   if(retC)
6747     {
6748       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6749       retC->setNodalConnectivity(c);
6750     }
6751   else
6752     {
6753       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6754       if(!retD)
6755         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6756       DataArrayInt *c=0,*ci=0;
6757       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6758       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6759       retD->setNodalConnectivity(cs,cis);
6760     }
6761   return ret.retn();
6762 }
6763
6764 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6765 {
6766   checkConnectivityFullyDefined();
6767     if(_types.size()!=1)
6768     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6769   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6770   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6771   if(cm.isDynamic())
6772     {
6773       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6774       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6775       throw INTERP_KERNEL::Exception(oss.str().c_str());
6776     }
6777   int nbCells=getNumberOfCells();
6778   int typi=(int)typ;
6779   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6780   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6781   int *outPtr=connOut->getPointer();
6782   const int *conn=_nodal_connec->begin();
6783   const int *connI=_nodal_connec_index->begin();
6784   nbNodesPerCell++;
6785   for(int i=0;i<nbCells;i++,connI++)
6786     {
6787       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6788         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6789       else
6790         {
6791           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 << ") !";
6792           throw INTERP_KERNEL::Exception(oss.str().c_str());
6793         }
6794     }
6795   return connOut.retn();
6796 }
6797
6798 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6799 {
6800   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6801   checkConnectivityFullyDefined();
6802   if(_types.size()!=1)
6803     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6804   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6805   if(lgth<nbCells)
6806     throw INTERP_KERNEL::Exception(msg0);
6807   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6808   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6809   int *cp(c->getPointer()),*cip(ci->getPointer());
6810   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6811   cip[0]=0;
6812   for(int i=0;i<nbCells;i++,cip++,incip++)
6813     {
6814       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6815       int delta(stop-strt);
6816       if(delta>=1)
6817         {
6818           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6819             cp=std::copy(incp+strt,incp+stop,cp);
6820           else
6821             throw INTERP_KERNEL::Exception(msg0);
6822         }
6823       else
6824         throw INTERP_KERNEL::Exception(msg0);
6825       cip[1]=cip[0]+delta;
6826     }
6827   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6828 }
6829
6830 /*!
6831  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6832  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6833  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6834  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6835  * are not used here to avoid the build of big permutation array.
6836  *
6837  * \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
6838  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6839  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6840  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6841  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6842  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6843  * \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
6844  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6845  */
6846 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6847                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6848                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6849 {
6850   std::vector<const MEDCouplingUMesh *> ms2;
6851   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6852     if(*it)
6853       {
6854         (*it)->checkConnectivityFullyDefined();
6855         ms2.push_back(*it);
6856       }
6857   if(ms2.empty())
6858     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6859   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6860   int meshDim=ms2[0]->getMeshDimension();
6861   std::vector<const MEDCouplingUMesh *> m1ssm;
6862   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6863   //
6864   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6865   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6866   int fake=0,rk=0;
6867   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6868   ret1->alloc(0,1); ret2->alloc(0,1);
6869   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6870     {
6871       if(meshDim!=(*it)->getMeshDimension())
6872         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6873       if(refCoo!=(*it)->getCoords())
6874         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6875       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6876       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6877       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6878       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6879         {
6880           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6881           m1ssmSingleAuto.push_back(singleCell);
6882           m1ssmSingle.push_back(singleCell);
6883           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6884         }
6885     }
6886   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6888   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6889   for(std::size_t i=0;i<m1ssm.size();i++)
6890     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6891   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6892   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6893   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6894   return ret0.retn();
6895 }
6896
6897 /*!
6898  * This method returns a newly created DataArrayInt instance.
6899  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6900  */
6901 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6902 {
6903   checkFullyDefined();
6904   const int *conn=_nodal_connec->getConstPointer();
6905   const int *connIndex=_nodal_connec_index->getConstPointer();
6906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6907   for(const int *w=begin;w!=end;w++)
6908     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6909       ret->pushBackSilent(*w);
6910   return ret.retn();
6911 }
6912
6913 /*!
6914  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6915  * are in [0:getNumberOfCells())
6916  */
6917 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6918 {
6919   checkFullyDefined();
6920   const int *conn=_nodal_connec->getConstPointer();
6921   const int *connI=_nodal_connec_index->getConstPointer();
6922   int nbOfCells=getNumberOfCells();
6923   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6924   int *tmp=new int[nbOfCells];
6925   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6926     {
6927       int j=0;
6928       for(const int *i=connI;i!=connI+nbOfCells;i++)
6929         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6930           tmp[std::distance(connI,i)]=j++;
6931     }
6932   DataArrayInt *ret=DataArrayInt::New();
6933   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6934   ret->copyStringInfoFrom(*da);
6935   int *retPtr=ret->getPointer();
6936   const int *daPtr=da->getConstPointer();
6937   int nbOfElems=da->getNbOfElems();
6938   for(int k=0;k<nbOfElems;k++)
6939     retPtr[k]=tmp[daPtr[k]];
6940   delete [] tmp;
6941   return ret;
6942 }
6943
6944 /*!
6945  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6946  * This method \b works \b for mesh sorted by type.
6947  * cells whose ids is in 'idsPerGeoType' array.
6948  * This method conserves coords and name of mesh.
6949  */
6950 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6951 {
6952   std::vector<int> code=getDistributionOfTypes();
6953   std::size_t nOfTypesInThis=code.size()/3;
6954   int sz=0,szOfType=0;
6955   for(std::size_t i=0;i<nOfTypesInThis;i++)
6956     {
6957       if(code[3*i]!=type)
6958         sz+=code[3*i+1];
6959       else
6960         szOfType=code[3*i+1];
6961     }
6962   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6963     if(*work<0 || *work>=szOfType)
6964       {
6965         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6966         oss << ". It should be in [0," << szOfType << ") !";
6967         throw INTERP_KERNEL::Exception(oss.str().c_str());
6968       }
6969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6970   int *idsPtr=idsTokeep->getPointer();
6971   int offset=0;
6972   for(std::size_t i=0;i<nOfTypesInThis;i++)
6973     {
6974       if(code[3*i]!=type)
6975         for(int j=0;j<code[3*i+1];j++)
6976           *idsPtr++=offset+j;
6977       else
6978         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6979       offset+=code[3*i+1];
6980     }
6981   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6982   ret->copyTinyInfoFrom(this);
6983   return ret.retn();
6984 }
6985
6986 /*!
6987  * This method returns a vector of size 'this->getNumberOfCells()'.
6988  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6989  */
6990 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6991 {
6992   int ncell=getNumberOfCells();
6993   std::vector<bool> ret(ncell);
6994   const int *cI=getNodalConnectivityIndex()->getConstPointer();
6995   const int *c=getNodalConnectivity()->getConstPointer();
6996   for(int i=0;i<ncell;i++)
6997     {
6998       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6999       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7000       ret[i]=cm.isQuadratic();
7001     }
7002   return ret;
7003 }
7004
7005 /*!
7006  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7007  */
7008 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7009 {
7010   if(other->getType()!=UNSTRUCTURED)
7011     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7012   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7013   return MergeUMeshes(this,otherC);
7014 }
7015
7016 /*!
7017  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7018  * computed by averaging coordinates of cell nodes, so this method is not a right
7019  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7020  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7021  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7022  *          components. The caller is to delete this array using decrRef() as it is
7023  *          no more needed.
7024  *  \throw If the coordinates array is not set.
7025  *  \throw If the nodal connectivity of cells is not defined.
7026  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7027  */
7028 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7029 {
7030   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7031   int spaceDim=getSpaceDimension();
7032   int nbOfCells=getNumberOfCells();
7033   ret->alloc(nbOfCells,spaceDim);
7034   ret->copyStringInfoFrom(*getCoords());
7035   double *ptToFill=ret->getPointer();
7036   const int *nodal=_nodal_connec->getConstPointer();
7037   const int *nodalI=_nodal_connec_index->getConstPointer();
7038   const double *coor=_coords->getConstPointer();
7039   for(int i=0;i<nbOfCells;i++)
7040     {
7041       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7042       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7043       ptToFill+=spaceDim;
7044     }
7045   return ret.retn();
7046 }
7047
7048 /*!
7049  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7050  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7051  * 
7052  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7053  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7054  * 
7055  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7056  * \throw If \a this is not fully defined (coordinates and connectivity)
7057  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7058  */
7059 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7060 {
7061   checkFullyDefined();
7062   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7063   int spaceDim=getSpaceDimension();
7064   int nbOfCells=getNumberOfCells();
7065   int nbOfNodes=getNumberOfNodes();
7066   ret->alloc(nbOfCells,spaceDim);
7067   double *ptToFill=ret->getPointer();
7068   const int *nodal=_nodal_connec->getConstPointer();
7069   const int *nodalI=_nodal_connec_index->getConstPointer();
7070   const double *coor=_coords->getConstPointer();
7071   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7072     {
7073       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7074       std::fill(ptToFill,ptToFill+spaceDim,0.);
7075       if(type!=INTERP_KERNEL::NORM_POLYHED)
7076         {
7077           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7078             {
7079               if(*conn>=0 && *conn<nbOfNodes)
7080                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7081               else
7082                 {
7083                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7084                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7085                 }
7086             }
7087           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7088           if(nbOfNodesInCell>0)
7089             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7090           else
7091             {
7092               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7093               throw INTERP_KERNEL::Exception(oss.str().c_str());
7094             }
7095         }
7096       else
7097         {
7098           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7099           s.erase(-1);
7100           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7101             {
7102               if(*it>=0 && *it<nbOfNodes)
7103                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7104               else
7105                 {
7106                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7107                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7108                 }
7109             }
7110           if(!s.empty())
7111             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7112           else
7113             {
7114               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7115               throw INTERP_KERNEL::Exception(oss.str().c_str());
7116             }
7117         }
7118     }
7119   return ret.retn();
7120 }
7121
7122 /*!
7123  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7124  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7125  * are specified via an array of cell ids. 
7126  *  \warning Validity of the specified cell ids is not checked! 
7127  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7128  *  \param [in] begin - an array of cell ids of interest.
7129  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7130  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7131  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7132  *          caller is to delete this array using decrRef() as it is no more needed. 
7133  *  \throw If the coordinates array is not set.
7134  *  \throw If the nodal connectivity of cells is not defined.
7135  *
7136  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7137  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7138  */
7139 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7140 {
7141   DataArrayDouble *ret=DataArrayDouble::New();
7142   int spaceDim=getSpaceDimension();
7143   int nbOfTuple=(int)std::distance(begin,end);
7144   ret->alloc(nbOfTuple,spaceDim);
7145   double *ptToFill=ret->getPointer();
7146   double *tmp=new double[spaceDim];
7147   const int *nodal=_nodal_connec->getConstPointer();
7148   const int *nodalI=_nodal_connec_index->getConstPointer();
7149   const double *coor=_coords->getConstPointer();
7150   for(const int *w=begin;w!=end;w++)
7151     {
7152       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7153       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7154       ptToFill+=spaceDim;
7155     }
7156   delete [] tmp;
7157   return ret;
7158 }
7159
7160 /*!
7161  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7162  * 
7163  */
7164 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7165 {
7166   if(!da)
7167     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7168   da->checkAllocated();
7169   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7170   ret->setCoords(da);
7171   int nbOfTuples=da->getNumberOfTuples();
7172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7174   c->alloc(2*nbOfTuples,1);
7175   cI->alloc(nbOfTuples+1,1);
7176   int *cp=c->getPointer();
7177   int *cip=cI->getPointer();
7178   *cip++=0;
7179   for(int i=0;i<nbOfTuples;i++)
7180     {
7181       *cp++=INTERP_KERNEL::NORM_POINT1;
7182       *cp++=i;
7183       *cip++=2*(i+1);
7184     }
7185   ret->setConnectivity(c,cI,true);
7186   return ret.retn();
7187 }
7188 /*!
7189  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7190  * Cells and nodes of
7191  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7192  *  \param [in] mesh1 - the first mesh.
7193  *  \param [in] mesh2 - the second mesh.
7194  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7195  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7196  *          is no more needed.
7197  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7198  *  \throw If the coordinates array is not set in none of the meshes.
7199  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7200  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7201  */
7202 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7203 {
7204   std::vector<const MEDCouplingUMesh *> tmp(2);
7205   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7206   return MergeUMeshes(tmp);
7207 }
7208
7209 /*!
7210  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7211  * Cells and nodes of
7212  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7213  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7214  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7215  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7216  *          is no more needed.
7217  *  \throw If \a a.size() == 0.
7218  *  \throw If \a a[ *i* ] == NULL.
7219  *  \throw If the coordinates array is not set in none of the meshes.
7220  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7221  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7222 */
7223 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7224 {
7225   std::size_t sz=a.size();
7226   if(sz==0)
7227     return MergeUMeshesLL(a);
7228   for(std::size_t ii=0;ii<sz;ii++)
7229     if(!a[ii])
7230       {
7231         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7232         throw INTERP_KERNEL::Exception(oss.str().c_str());
7233       }
7234   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7235   std::vector< const MEDCouplingUMesh * > aa(sz);
7236   int spaceDim=-3;
7237   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7238     {
7239       const MEDCouplingUMesh *cur=a[i];
7240       const DataArrayDouble *coo=cur->getCoords();
7241       if(coo)
7242         spaceDim=coo->getNumberOfComponents();
7243     }
7244   if(spaceDim==-3)
7245     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7246   for(std::size_t i=0;i<sz;i++)
7247     {
7248       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7249       aa[i]=bb[i];
7250     }
7251   return MergeUMeshesLL(aa);
7252 }
7253
7254 /// @cond INTERNAL
7255
7256 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7257 {
7258   if(a.empty())
7259     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7260   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7261   int meshDim=(*it)->getMeshDimension();
7262   int nbOfCells=(*it)->getNumberOfCells();
7263   int meshLgth=(*it++)->getMeshLength();
7264   for(;it!=a.end();it++)
7265     {
7266       if(meshDim!=(*it)->getMeshDimension())
7267         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7268       nbOfCells+=(*it)->getNumberOfCells();
7269       meshLgth+=(*it)->getMeshLength();
7270     }
7271   std::vector<const MEDCouplingPointSet *> aps(a.size());
7272   std::copy(a.begin(),a.end(),aps.begin());
7273   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7274   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7275   ret->setCoords(pts);
7276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7277   c->alloc(meshLgth,1);
7278   int *cPtr=c->getPointer();
7279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7280   cI->alloc(nbOfCells+1,1);
7281   int *cIPtr=cI->getPointer();
7282   *cIPtr++=0;
7283   int offset=0;
7284   int offset2=0;
7285   for(it=a.begin();it!=a.end();it++)
7286     {
7287       int curNbOfCell=(*it)->getNumberOfCells();
7288       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7289       const int *curC=(*it)->_nodal_connec->getConstPointer();
7290       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7291       for(int j=0;j<curNbOfCell;j++)
7292         {
7293           const int *src=curC+curCI[j];
7294           *cPtr++=*src++;
7295           for(;src!=curC+curCI[j+1];src++,cPtr++)
7296             {
7297               if(*src!=-1)
7298                 *cPtr=*src+offset2;
7299               else
7300                 *cPtr=-1;
7301             }
7302         }
7303       offset+=curCI[curNbOfCell];
7304       offset2+=(*it)->getNumberOfNodes();
7305     }
7306   //
7307   ret->setConnectivity(c,cI,true);
7308   return ret.retn();
7309 }
7310
7311 /// @endcond
7312
7313 /*!
7314  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7315  * dimension and sharing the node coordinates array.
7316  * All cells of the first mesh precede all cells of the second mesh
7317  * within the result mesh. 
7318  *  \param [in] mesh1 - the first mesh.
7319  *  \param [in] mesh2 - the second mesh.
7320  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7321  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7322  *          is no more needed.
7323  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7324  *  \throw If the meshes do not share the node coordinates array.
7325  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7326  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7327  */
7328 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7329 {
7330   std::vector<const MEDCouplingUMesh *> tmp(2);
7331   tmp[0]=mesh1; tmp[1]=mesh2;
7332   return MergeUMeshesOnSameCoords(tmp);
7333 }
7334
7335 /*!
7336  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7337  * dimension and sharing the node coordinates array.
7338  * All cells of the *i*-th mesh precede all cells of the
7339  * (*i*+1)-th mesh within the result mesh.
7340  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7341  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7342  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7343  *          is no more needed.
7344  *  \throw If \a a.size() == 0.
7345  *  \throw If \a a[ *i* ] == NULL.
7346  *  \throw If the meshes do not share the node coordinates array.
7347  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7348  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7349  */
7350 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7351 {
7352   if(meshes.empty())
7353     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7354   for(std::size_t ii=0;ii<meshes.size();ii++)
7355     if(!meshes[ii])
7356       {
7357         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7358         throw INTERP_KERNEL::Exception(oss.str().c_str());
7359       }
7360   const DataArrayDouble *coords=meshes.front()->getCoords();
7361   int meshDim=meshes.front()->getMeshDimension();
7362   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7363   int meshLgth=0;
7364   int meshIndexLgth=0;
7365   for(;iter!=meshes.end();iter++)
7366     {
7367       if(coords!=(*iter)->getCoords())
7368         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7369       if(meshDim!=(*iter)->getMeshDimension())
7370         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7371       meshLgth+=(*iter)->getMeshLength();
7372       meshIndexLgth+=(*iter)->getNumberOfCells();
7373     }
7374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7375   nodal->alloc(meshLgth,1);
7376   int *nodalPtr=nodal->getPointer();
7377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7378   nodalIndex->alloc(meshIndexLgth+1,1);
7379   int *nodalIndexPtr=nodalIndex->getPointer();
7380   int offset=0;
7381   for(iter=meshes.begin();iter!=meshes.end();iter++)
7382     {
7383       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7384       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7385       int nbOfCells=(*iter)->getNumberOfCells();
7386       int meshLgth2=(*iter)->getMeshLength();
7387       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7388       if(iter!=meshes.begin())
7389         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7390       else
7391         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7392       offset+=meshLgth2;
7393     }
7394   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7395   ret->setName("merge");
7396   ret->setMeshDimension(meshDim);
7397   ret->setConnectivity(nodal,nodalIndex,true);
7398   ret->setCoords(coords);
7399   return ret;
7400 }
7401
7402 /*!
7403  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7404  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7405  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7406  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7407  * New" mode are returned for each input mesh.
7408  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7409  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7410  *          valid values [0,1,2], see zipConnectivityTraducer().
7411  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7412  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7413  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7414  *          no more needed.
7415  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7416  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7417  *          is no more needed.
7418  *  \throw If \a meshes.size() == 0.
7419  *  \throw If \a meshes[ *i* ] == NULL.
7420  *  \throw If the meshes do not share the node coordinates array.
7421  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7422  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7423  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7424  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7425  */
7426 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7427 {
7428   //All checks are delegated to MergeUMeshesOnSameCoords
7429   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7431   corr.resize(meshes.size());
7432   std::size_t nbOfMeshes=meshes.size();
7433   int offset=0;
7434   const int *o2nPtr=o2n->getConstPointer();
7435   for(std::size_t i=0;i<nbOfMeshes;i++)
7436     {
7437       DataArrayInt *tmp=DataArrayInt::New();
7438       int curNbOfCells=meshes[i]->getNumberOfCells();
7439       tmp->alloc(curNbOfCells,1);
7440       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7441       offset+=curNbOfCells;
7442       tmp->setName(meshes[i]->getName().c_str());
7443       corr[i]=tmp;
7444     }
7445   return ret.retn();
7446 }
7447
7448 /*!
7449  * Makes all given meshes share the nodal connectivity array. The common connectivity
7450  * array is created by concatenating the connectivity arrays of all given meshes. All
7451  * the given meshes must be of the same space dimension but dimension of cells **can
7452  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7453  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7454  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7455  *  \param [in,out] meshes - a vector of meshes to update.
7456  *  \throw If any of \a meshes is NULL.
7457  *  \throw If the coordinates array is not set in any of \a meshes.
7458  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7459  *  \throw If \a meshes are of different space dimension.
7460  */
7461 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7462 {
7463   std::size_t sz=meshes.size();
7464   if(sz==0 || sz==1)
7465     return;
7466   std::vector< const DataArrayDouble * > coords(meshes.size());
7467   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7468   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7469     {
7470       if((*it))
7471         {
7472           (*it)->checkConnectivityFullyDefined();
7473           const DataArrayDouble *coo=(*it)->getCoords();
7474           if(coo)
7475             *it2=coo;
7476           else
7477             {
7478               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7479               oss << " has no coordinate array defined !";
7480               throw INTERP_KERNEL::Exception(oss.str().c_str());
7481             }
7482         }
7483       else
7484         {
7485           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7486           oss << " is null !";
7487           throw INTERP_KERNEL::Exception(oss.str().c_str());
7488         }
7489     }
7490   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7491   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7492   int offset=(*it)->getNumberOfNodes();
7493   (*it++)->setCoords(res);
7494   for(;it!=meshes.end();it++)
7495     {
7496       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7497       (*it)->setCoords(res);
7498       (*it)->shiftNodeNumbersInConn(offset);
7499       offset+=oldNumberOfNodes;
7500     }
7501 }
7502
7503 /*!
7504  * Merges nodes coincident with a given precision within all given meshes that share
7505  * the nodal connectivity array. The given meshes **can be of different** mesh
7506  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7507  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7508  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7509  *  \param [in,out] meshes - a vector of meshes to update.
7510  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7511  *  \throw If any of \a meshes is NULL.
7512  *  \throw If the \a meshes do not share the same node coordinates array.
7513  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7514  */
7515 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7516 {
7517   if(meshes.empty())
7518     return ;
7519   std::set<const DataArrayDouble *> s;
7520   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7521     {
7522       if(*it)
7523         s.insert((*it)->getCoords());
7524       else
7525         {
7526           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 !";
7527           throw INTERP_KERNEL::Exception(oss.str().c_str());
7528         }
7529     }
7530   if(s.size()!=1)
7531     {
7532       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 !";
7533       throw INTERP_KERNEL::Exception(oss.str().c_str());
7534     }
7535   const DataArrayDouble *coo=*(s.begin());
7536   if(!coo)
7537     return;
7538   //
7539   DataArrayInt *comm,*commI;
7540   coo->findCommonTuples(eps,-1,comm,commI);
7541   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7542   int oldNbOfNodes=coo->getNumberOfTuples();
7543   int newNbOfNodes;
7544   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7545   if(oldNbOfNodes==newNbOfNodes)
7546     return ;
7547   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7548   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7549     {
7550       (*it)->renumberNodesInConn(o2n->getConstPointer());
7551       (*it)->setCoords(newCoords);
7552     } 
7553 }
7554
7555 /*!
7556  * 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.
7557  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7558  * \param isQuad specifies the policy of connectivity.
7559  * @ret in/out parameter in which the result will be append
7560  */
7561 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7562 {
7563   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7564   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7565   ret.push_back(cm.getExtrudedType());
7566   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7567   switch(flatType)
7568     {
7569     case INTERP_KERNEL::NORM_POINT1:
7570       {
7571         ret.push_back(connBg[1]);
7572         ret.push_back(connBg[1]+nbOfNodesPerLev);
7573         break;
7574       }
7575     case INTERP_KERNEL::NORM_SEG2:
7576       {
7577         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7578         ret.insert(ret.end(),conn,conn+4);
7579         break;
7580       }
7581     case INTERP_KERNEL::NORM_SEG3:
7582       {
7583         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7584         ret.insert(ret.end(),conn,conn+8);
7585         break;
7586       }
7587     case INTERP_KERNEL::NORM_QUAD4:
7588       {
7589         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7590         ret.insert(ret.end(),conn,conn+8);
7591         break;
7592       }
7593     case INTERP_KERNEL::NORM_TRI3:
7594       {
7595         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7596         ret.insert(ret.end(),conn,conn+6);
7597         break;
7598       }
7599     case INTERP_KERNEL::NORM_TRI6:
7600       {
7601         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,
7602                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7603         ret.insert(ret.end(),conn,conn+15);
7604         break;
7605       }
7606     case INTERP_KERNEL::NORM_QUAD8:
7607       {
7608         int conn[20]={
7609           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7610           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7611           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7612         };
7613         ret.insert(ret.end(),conn,conn+20);
7614         break;
7615       }
7616     case INTERP_KERNEL::NORM_POLYGON:
7617       {
7618         std::back_insert_iterator< std::vector<int> > ii(ret);
7619         std::copy(connBg+1,connEnd,ii);
7620         *ii++=-1;
7621         std::reverse_iterator<const int *> rConnBg(connEnd);
7622         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7623         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7624         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7625         for(std::size_t i=0;i<nbOfRadFaces;i++)
7626           {
7627             *ii++=-1;
7628             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7629             std::copy(conn,conn+4,ii);
7630           }
7631         break;
7632       }
7633     default:
7634       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7635     }
7636 }
7637
7638 /*!
7639  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7640  */
7641 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7642 {
7643   double v[3]={0.,0.,0.};
7644   std::size_t sz=std::distance(begin,end);
7645   if(isQuadratic)
7646     sz/=2;
7647   for(std::size_t i=0;i<sz;i++)
7648     {
7649       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];
7650       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7651       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7652     }
7653   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7654 }
7655
7656 /*!
7657  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7658  */
7659 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7660 {
7661   std::vector<std::pair<int,int> > edges;
7662   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7663   const int *bgFace=begin;
7664   for(std::size_t i=0;i<nbOfFaces;i++)
7665     {
7666       const int *endFace=std::find(bgFace+1,end,-1);
7667       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7668       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7669         {
7670           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7671           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7672             return false;
7673           edges.push_back(p1);
7674         }
7675       bgFace=endFace+1;
7676     }
7677   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7678 }
7679
7680 /*!
7681  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7682  */
7683 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7684 {
7685   double vec0[3],vec1[3];
7686   std::size_t sz=std::distance(begin,end);
7687   if(sz%2!=0)
7688     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7689   int nbOfNodes=(int)sz/2;
7690   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7691   const double *pt0=coords+3*begin[0];
7692   const double *pt1=coords+3*begin[nbOfNodes];
7693   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7694   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7695 }
7696
7697 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7698 {
7699   std::size_t sz=std::distance(begin,end);
7700   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7701   std::size_t nbOfNodes(sz/2);
7702   std::copy(begin,end,(int *)tmp);
7703   for(std::size_t j=1;j<nbOfNodes;j++)
7704     {
7705       begin[j]=tmp[nbOfNodes-j];
7706       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7707     }
7708 }
7709
7710 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7711 {
7712   std::size_t sz=std::distance(begin,end);
7713   if(sz!=4)
7714     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7715   double vec0[3],vec1[3];
7716   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7717   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]; 
7718   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;
7719 }
7720
7721 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7722 {
7723   std::size_t sz=std::distance(begin,end);
7724   if(sz!=5)
7725     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7726   double vec0[3];
7727   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7728   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7729   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7730 }
7731
7732 /*!
7733  * 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 ) 
7734  * 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
7735  * a 2D space.
7736  *
7737  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7738  * \param [in] coords the coordinates with nb of components exactly equal to 3
7739  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7740  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7741  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7742  */
7743 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7744 {
7745   int nbFaces=std::count(begin+1,end,-1)+1;
7746   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7747   double *vPtr=v->getPointer();
7748   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7749   double *pPtr=p->getPointer();
7750   const int *stFaceConn=begin+1;
7751   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7752     {
7753       const int *endFaceConn=std::find(stFaceConn,end,-1);
7754       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7755       stFaceConn=endFaceConn+1;
7756     }
7757   pPtr=p->getPointer(); vPtr=v->getPointer();
7758   DataArrayInt *comm1=0,*commI1=0;
7759   v->findCommonTuples(eps,-1,comm1,commI1);
7760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7761   const int *comm1Ptr=comm1->getConstPointer();
7762   const int *commI1Ptr=commI1->getConstPointer();
7763   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7764   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7765   //
7766   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7767   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7768   mm->finishInsertingCells();
7769   //
7770   for(int i=0;i<nbOfGrps1;i++)
7771     {
7772       int vecId=comm1Ptr[commI1Ptr[i]];
7773       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7774       DataArrayInt *comm2=0,*commI2=0;
7775       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7776       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7777       const int *comm2Ptr=comm2->getConstPointer();
7778       const int *commI2Ptr=commI2->getConstPointer();
7779       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7780       for(int j=0;j<nbOfGrps2;j++)
7781         {
7782           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7783             {
7784               res->insertAtTheEnd(begin,end);
7785               res->pushBackSilent(-1);
7786             }
7787           else
7788             {
7789               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7790               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7791               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7792               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7793               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7794               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7795               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7796               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7797               const int *idsNodePtr=idsNode->getConstPointer();
7798               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];
7799               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7800               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7801               if(std::abs(norm)>eps)
7802                 {
7803                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7804                   mm3->rotate(center,vec,angle);
7805                 }
7806               mm3->changeSpaceDimension(2);
7807               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7808               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7809               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7810               int nbOfCells=mm4->getNumberOfCells();
7811               for(int k=0;k<nbOfCells;k++)
7812                 {
7813                   int l=0;
7814                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7815                     res->pushBackSilent(idsNodePtr[*work]);
7816                   res->pushBackSilent(-1);
7817                 }
7818             }
7819         }
7820     }
7821   res->popBackSilent();
7822 }
7823
7824 /*!
7825  * 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
7826  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7827  * 
7828  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7829  * \param [in] coords coordinates expected to have 3 components.
7830  * \param [in] begin start of the nodal connectivity of the face.
7831  * \param [in] end end of the nodal connectivity (excluded) of the face.
7832  * \param [out] v the normalized vector of size 3
7833  * \param [out] p the pos of plane
7834  */
7835 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7836 {
7837   std::size_t nbPoints=std::distance(begin,end);
7838   if(nbPoints<3)
7839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7840   double vec[3]={0.,0.,0.};
7841   std::size_t j=0;
7842   bool refFound=false;
7843   for(;j<nbPoints-1 && !refFound;j++)
7844     {
7845       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7846       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7847       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7848       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7849       if(norm>eps)
7850         {
7851           refFound=true;
7852           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7853         }
7854     }
7855   for(std::size_t i=j;i<nbPoints-1;i++)
7856     {
7857       double curVec[3];
7858       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7859       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7860       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7861       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7862       if(norm<eps)
7863         continue;
7864       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7865       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];
7866       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7867       if(norm>eps)
7868         {
7869           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7870           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7871           return ;
7872         }
7873     }
7874   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7875 }
7876
7877 /*!
7878  * This method tries to obtain a well oriented polyhedron.
7879  * If the algorithm fails, an exception will be thrown.
7880  */
7881 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7882 {
7883   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7884   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7885   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7886   isPerm[0]=true;
7887   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7888   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7889   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7890   //
7891   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7892     {
7893       bgFace=begin;
7894       std::size_t smthChanged=0;
7895       for(std::size_t i=0;i<nbOfFaces;i++)
7896         {
7897           endFace=std::find(bgFace+1,end,-1);
7898           nbOfEdgesInFace=std::distance(bgFace,endFace);
7899           if(!isPerm[i])
7900             {
7901               bool b;
7902               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7903                 {
7904                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7905                   std::pair<int,int> p2(p1.second,p1.first);
7906                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7907                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7908                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7909                 }
7910               if(isPerm[i])
7911                 { 
7912                   if(!b)
7913                     std::reverse(bgFace+1,endFace);
7914                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7915                     {
7916                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7917                       std::pair<int,int> p2(p1.second,p1.first);
7918                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7919                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7920                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7921                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7922                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7923                       if(it!=edgesOK.end())
7924                         {
7925                           edgesOK.erase(it);
7926                           edgesFinished.push_back(p1);
7927                         }
7928                       else
7929                         edgesOK.push_back(p1);
7930                     }
7931                 }
7932             }
7933           bgFace=endFace+1;
7934         }
7935       if(smthChanged==0)
7936         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7937     }
7938   if(!edgesOK.empty())
7939     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7940   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7941     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7942       bgFace=begin;
7943       for(std::size_t i=0;i<nbOfFaces;i++)
7944         {
7945           endFace=std::find(bgFace+1,end,-1);
7946           std::reverse(bgFace+1,endFace);
7947           bgFace=endFace+1;
7948         }
7949     }
7950 }
7951
7952 /*!
7953  * This method makes the assumption spacedimension == meshdimension == 2.
7954  * This method works only for linear cells.
7955  * 
7956  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7957  */
7958 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7959 {
7960   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7961     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7962   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7963   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7964   int nbOfNodesExpected=m->getNumberOfNodes();
7965   if(m->getNumberOfCells()!=nbOfNodesExpected)
7966     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7967   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7968   const int *n2oPtr=n2o->getConstPointer();
7969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7970   m->getReverseNodalConnectivity(revNodal,revNodalI);
7971   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7972   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7973   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7975   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7976   if(nbOfNodesExpected<1)
7977     return ret.retn();
7978   int prevCell=0;
7979   int prevNode=nodalPtr[nodalIPtr[0]+1];
7980   *work++=n2oPtr[prevNode];
7981   for(int i=1;i<nbOfNodesExpected;i++)
7982     {
7983       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7984         {
7985           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7986           conn.erase(prevNode);
7987           if(conn.size()==1)
7988             {
7989               int curNode=*(conn.begin());
7990               *work++=n2oPtr[curNode];
7991               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7992               shar.erase(prevCell);
7993               if(shar.size()==1)
7994                 {
7995                   prevCell=*(shar.begin());
7996                   prevNode=curNode;
7997                 }
7998               else
7999                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8000             }
8001           else
8002             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8003         }
8004       else
8005         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8006     }
8007   return ret.retn();
8008 }
8009
8010 /*!
8011  * This method makes the assumption spacedimension == meshdimension == 3.
8012  * This method works only for linear cells.
8013  * 
8014  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8015  */
8016 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8017 {
8018   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8019     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8020   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8021   const int *conn=m->getNodalConnectivity()->getConstPointer();
8022   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8023   int nbOfCells=m->getNumberOfCells();
8024   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8025   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8026   if(nbOfCells<1)
8027     return ret.retn();
8028   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8029   for(int i=1;i<nbOfCells;i++)
8030     {
8031       *work++=-1;
8032       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8033     }
8034   return ret.retn();
8035 }
8036
8037 /*!
8038  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8039  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8040  */
8041 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8042 {
8043   double *w=zipFrmt;
8044   if(spaceDim==3)
8045     for(int i=0;i<nbOfNodesInCell;i++)
8046       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8047   else if(spaceDim==2)
8048     {
8049       for(int i=0;i<nbOfNodesInCell;i++)
8050         {
8051           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8052           *w++=0.;
8053         }
8054     }
8055   else
8056     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8057 }
8058
8059 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8060 {
8061   int nbOfCells=getNumberOfCells();
8062   if(nbOfCells<=0)
8063     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8064   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};
8065   ofs << "  <" << getVTKDataSetType() << ">\n";
8066   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8067   ofs << "      <PointData>\n" << pointData << std::endl;
8068   ofs << "      </PointData>\n";
8069   ofs << "      <CellData>\n" << cellData << std::endl;
8070   ofs << "      </CellData>\n";
8071   ofs << "      <Points>\n";
8072   if(getSpaceDimension()==3)
8073     _coords->writeVTK(ofs,8,"Points");
8074   else
8075     {
8076       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8077       coo->writeVTK(ofs,8,"Points");
8078     }
8079   ofs << "      </Points>\n";
8080   ofs << "      <Cells>\n";
8081   const int *cPtr=_nodal_connec->getConstPointer();
8082   const int *cIPtr=_nodal_connec_index->getConstPointer();
8083   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8084   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8085   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8086   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8087   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8088   int szFaceOffsets=0,szConn=0;
8089   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8090     {
8091       *w2=cPtr[cIPtr[i]];
8092       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8093         {
8094           *w1=-1;
8095           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8096           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8097         }
8098       else
8099         {
8100           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8101           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8102           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8103           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8104           w4=std::copy(c.begin(),c.end(),w4);
8105         }
8106     }
8107   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8108   types->writeVTK(ofs,8,"UInt8","types");
8109   offsets->writeVTK(ofs,8,"Int32","offsets");
8110   if(szFaceOffsets!=0)
8111     {//presence of Polyhedra
8112       connectivity->reAlloc(szConn);
8113       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8114       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8115       w1=faces->getPointer();
8116       for(int i=0;i<nbOfCells;i++)
8117         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8118           {
8119             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8120             *w1++=nbFaces;
8121             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8122             for(int j=0;j<nbFaces;j++)
8123               {
8124                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8125                 *w1++=(int)std::distance(w6,w5);
8126                 w1=std::copy(w6,w5,w1);
8127                 w6=w5+1;
8128               }
8129           }
8130       faces->writeVTK(ofs,8,"Int32","faces");
8131     }
8132   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8133   ofs << "      </Cells>\n";
8134   ofs << "    </Piece>\n";
8135   ofs << "  </" << getVTKDataSetType() << ">\n";
8136 }
8137
8138 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8139 {
8140   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8141   if(_mesh_dim==-2)
8142     { stream << " Not set !"; return ; }
8143   stream << " Mesh dimension : " << _mesh_dim << ".";
8144   if(_mesh_dim==-1)
8145     return ;
8146   if(!_coords)
8147     { stream << " No coordinates set !"; return ; }
8148   if(!_coords->isAllocated())
8149     { stream << " Coordinates set but not allocated !"; return ; }
8150   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8151   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8152   if(!_nodal_connec_index)
8153     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8154   if(!_nodal_connec_index->isAllocated())
8155     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8156   int lgth=_nodal_connec_index->getNumberOfTuples();
8157   int cpt=_nodal_connec_index->getNumberOfComponents();
8158   if(cpt!=1 || lgth<1)
8159     return ;
8160   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8161 }
8162
8163 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8164 {
8165   return std::string("UnstructuredGrid");
8166 }
8167
8168 /*!
8169  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8170  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8171  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8172  * meshes.
8173  *  \param [in] m1 - the first input mesh which is a partitioned object.
8174  *  \param [in] m2 - the second input mesh which is a partition tool.
8175  *  \param [in] eps - precision used to detect coincident mesh entities.
8176  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8177  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8178  *         this array using decrRef() as it is no more needed.
8179  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8180  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8181  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8182  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8183  *         it is no more needed.  
8184  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8185  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8186  *         is no more needed.  
8187  *  \throw If the coordinates array is not set in any of the meshes.
8188  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8189  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8190  */
8191 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8192 {
8193   m1->checkFullyDefined();
8194   m2->checkFullyDefined();
8195   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8196     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8197   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8198   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8199   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8200   std::vector<double> addCoo,addCoordsQuadratic;
8201   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8202   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8203   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8204                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8205   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8206   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8207   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8208   std::vector< std::vector<int> > intersectEdge2;
8209   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8210   subDiv2.clear(); dd5=0; dd6=0;
8211   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8212   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8213   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8214                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8215   //
8216   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8217   addCooDa->alloc((int)(addCoo.size())/2,2);
8218   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8219   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8220   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8221   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8222   std::vector<const DataArrayDouble *> coordss(4);
8223   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8224   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8225   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8226   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8227   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8228   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8229   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8230   ret->setConnectivity(conn,connI,true);
8231   ret->setCoords(coo);
8232   cellNb1=c1.retn(); cellNb2=c2.retn();
8233   return ret.retn();
8234 }
8235
8236 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8237                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8238                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8239                                                          const std::vector<double>& addCoords,
8240                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8241 {
8242   static const int SPACEDIM=2;
8243   std::vector<double> bbox1,bbox2;
8244   const double *coo1=m1->getCoords()->getConstPointer();
8245   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8246   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8247   int offset1=m1->getNumberOfNodes();
8248   const double *coo2=m2->getCoords()->getConstPointer();
8249   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8250   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8251   int offset2=offset1+m2->getNumberOfNodes();
8252   int offset3=offset2+((int)addCoords.size())/2;
8253   m1->getBoundingBoxForBBTree(bbox1);
8254   m2->getBoundingBoxForBBTree(bbox2);
8255   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8256   int ncell1=m1->getNumberOfCells();
8257   crI.push_back(0);
8258   for(int i=0;i<ncell1;i++)
8259     {
8260       std::vector<int> candidates2;
8261       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8262       std::map<INTERP_KERNEL::Node *,int> mapp;
8263       std::map<int,INTERP_KERNEL::Node *> mappRev;
8264       INTERP_KERNEL::QuadraticPolygon pol1;
8265       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8266       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8267       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8268       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8269                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8270       //
8271       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
8272       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8273       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8274       for(it1.first();!it1.finished();it1.next())
8275         edges1.insert(it1.current()->getPtr());
8276       //
8277       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8278       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8279       int ii=0;
8280       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8281         {
8282           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8283           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8284           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8285           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8286                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8287         }
8288       ii=0;
8289       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8290         {
8291           pol1.initLocationsWithOther(pol2s[ii]);
8292           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8293           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8294           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8295         }
8296       if(!edges1.empty())
8297         {
8298           try
8299             {
8300               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8301             }
8302           catch(INTERP_KERNEL::Exception& e)
8303             {
8304               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();
8305               throw INTERP_KERNEL::Exception(oss.str().c_str());
8306             }
8307         }
8308       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8309         (*it).second->decrRef();
8310     }
8311 }
8312
8313 /*!
8314  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8315  * 
8316  */
8317 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8318                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8319                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8320                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8321                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8322 {
8323   static const int SPACEDIM=2;
8324   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8325   desc2=DataArrayInt::New();
8326   descIndx2=DataArrayInt::New();
8327   revDesc2=DataArrayInt::New();
8328   revDescIndx2=DataArrayInt::New();
8329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8330   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8331   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8332   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8333   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8334   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8335   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8336   std::vector<double> bbox1,bbox2;
8337   m1Desc->getBoundingBoxForBBTree(bbox1);
8338   m2Desc->getBoundingBoxForBBTree(bbox2);
8339   int ncell1=m1Desc->getNumberOfCells();
8340   int ncell2=m2Desc->getNumberOfCells();
8341   intersectEdge1.resize(ncell1);
8342   colinear2.resize(ncell2);
8343   subDiv2.resize(ncell2);
8344   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8345   std::vector<int> candidates1(1);
8346   int offset1=m1->getNumberOfNodes();
8347   int offset2=offset1+m2->getNumberOfNodes();
8348   for(int i=0;i<ncell1;i++)
8349     {
8350       std::vector<int> candidates2;
8351       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8352       if(!candidates2.empty())
8353         {
8354           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8355           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8356           candidates1[0]=i;
8357           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8358           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8359           delete pol2;
8360           delete pol1;
8361         }
8362       else
8363         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8364     }
8365   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8366   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8367 }
8368
8369 /*!
8370  * This method performs the 2nd step of Partition of 2D mesh.
8371  * This method has 4 inputs :
8372  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8373  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8374  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8375  * 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'
8376  * \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'
8377  * \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.
8378  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8379  */
8380 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)
8381 {
8382   int offset1=m1->getNumberOfNodes();
8383   int ncell=m2->getNumberOfCells();
8384   const int *c=m2->getNodalConnectivity()->getConstPointer();
8385   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8386   const double *coo=m2->getCoords()->getConstPointer();
8387   const double *cooBis=m1->getCoords()->getConstPointer();
8388   int offset2=offset1+m2->getNumberOfNodes();
8389   intersectEdge.resize(ncell);
8390   for(int i=0;i<ncell;i++,cI++)
8391     {
8392       const std::vector<int>& divs=subDiv[i];
8393       int nnode=cI[1]-cI[0]-1;
8394       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8395       std::map<INTERP_KERNEL::Node *, int> mapp22;
8396       for(int j=0;j<nnode;j++)
8397         {
8398           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8399           int nnid=c[(*cI)+j+1];
8400           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8401           mapp22[nn]=nnid+offset1;
8402         }
8403       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8404       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8405         ((*it).second.first)->decrRef();
8406       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8407       std::map<INTERP_KERNEL::Node *,int> mapp3;
8408       for(std::size_t j=0;j<divs.size();j++)
8409         {
8410           int id=divs[j];
8411           INTERP_KERNEL::Node *tmp=0;
8412           if(id<offset1)
8413             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8414           else if(id<offset2)
8415             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8416           else
8417             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8418           addNodes[j]=tmp;
8419           mapp3[tmp]=id;
8420         }
8421       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8422       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8423         (*it)->decrRef();
8424       e->decrRef();
8425     }
8426 }
8427
8428 /*!
8429  * 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).
8430  * 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
8431  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8432  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8433  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8434  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8435  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8436  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8437  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8438  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8439  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8440  * \param [out] cut3DSuf input/output param.
8441  */
8442 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8443                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8444                                                    const int *desc, const int *descIndx, 
8445                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8446 {
8447   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8448   int nbOf3DSurfCell=(int)cut3DSurf.size();
8449   for(int i=0;i<nbOf3DSurfCell;i++)
8450     {
8451       std::vector<int> res;
8452       int offset=descIndx[i];
8453       int nbOfSeg=descIndx[i+1]-offset;
8454       for(int j=0;j<nbOfSeg;j++)
8455         {
8456           int edgeId=desc[offset+j];
8457           int status=cut3DCurve[edgeId];
8458           if(status!=-2)
8459             {
8460               if(status>-1)
8461                 res.push_back(status);
8462               else
8463                 {
8464                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8465                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8466                 }
8467             }
8468         }
8469       switch(res.size())
8470         {
8471         case 2:
8472           {
8473             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8474             break;
8475           }
8476         case 1:
8477         case 0:
8478           {
8479             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8480             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8481             if(res.size()==2)
8482               {
8483                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8484               }
8485             else
8486               {
8487                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8488               }
8489             break;
8490           }
8491         default:
8492           {// case when plane is on a multi colinear edge of a polyhedron
8493             if((int)res.size()==2*nbOfSeg)
8494               {
8495                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8496               }
8497             else
8498               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8499           }
8500         }
8501     }
8502 }
8503
8504 /*!
8505  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8506  * 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).
8507  * 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
8508  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8509  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8510  * \param desc is the descending connectivity 3D->3DSurf
8511  * \param descIndx is the descending connectivity index 3D->3DSurf
8512  */
8513 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8514                                                   const int *desc, const int *descIndx,
8515                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8516 {
8517   checkFullyDefined();
8518   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8519     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8520   const int *nodal3D=_nodal_connec->getConstPointer();
8521   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8522   int nbOfCells=getNumberOfCells();
8523   for(int i=0;i<nbOfCells;i++)
8524     {
8525       std::map<int, std::set<int> > m;
8526       int offset=descIndx[i];
8527       int nbOfFaces=descIndx[i+1]-offset;
8528       int start=-1;
8529       int end=-1;
8530       for(int j=0;j<nbOfFaces;j++)
8531         {
8532           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8533           if(p.first!=-1 && p.second!=-1)
8534             {
8535               if(p.first!=-2)
8536                 {
8537                   start=p.first; end=p.second;
8538                   m[p.first].insert(p.second);
8539                   m[p.second].insert(p.first);
8540                 }
8541               else
8542                 {
8543                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8544                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8545                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8546                   INTERP_KERNEL::NormalizedCellType cmsId;
8547                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8548                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8549                   for(unsigned k=0;k<nbOfNodesSon;k++)
8550                     {
8551                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8552                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8553                     }
8554                 }
8555             }
8556         }
8557       if(m.empty())
8558         continue;
8559       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8560       int prev=end;
8561       while(end!=start)
8562         {
8563           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8564           const std::set<int>& s=(*it).second;
8565           std::set<int> s2; s2.insert(prev);
8566           std::set<int> s3;
8567           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8568           if(s3.size()==1)
8569             {
8570               int val=*s3.begin();
8571               conn.push_back(start);
8572               prev=start;
8573               start=val;
8574             }
8575           else
8576             start=end;
8577         }
8578       conn.push_back(end);
8579       if(conn.size()>3)
8580         {
8581           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8582           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8583           cellIds->pushBackSilent(i);
8584         }
8585     }
8586 }
8587
8588 /*!
8589  * 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
8590  * 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
8591  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8592  * 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
8593  * 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.
8594  * 
8595  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8596  */
8597 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8598 {
8599   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8600   if(sz>=4)
8601     {
8602       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8603       if(cm.getDimension()==2)
8604         {
8605           const int *node=nodalConnBg+1;
8606           int startNode=*node++;
8607           double refX=coords[2*startNode];
8608           for(;node!=nodalConnEnd;node++)
8609             {
8610               if(coords[2*(*node)]<refX)
8611                 {
8612                   startNode=*node;
8613                   refX=coords[2*startNode];
8614                 }
8615             }
8616           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8617           refX=1e300;
8618           double tmp1;
8619           double tmp2[2];
8620           double angle0=-M_PI/2;
8621           //
8622           int nextNode=-1;
8623           int prevNode=-1;
8624           double resRef;
8625           double angleNext=0.;
8626           while(nextNode!=startNode)
8627             {
8628               nextNode=-1;
8629               resRef=1e300;
8630               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8631                 {
8632                   if(*node!=tmpOut.back() && *node!=prevNode)
8633                     {
8634                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8635                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8636                       double res;
8637                       if(angleM<=angle0)
8638                         res=angle0-angleM;
8639                       else
8640                         res=angle0-angleM+2.*M_PI;
8641                       if(res<resRef)
8642                         {
8643                           nextNode=*node;
8644                           resRef=res;
8645                           angleNext=angleM;
8646                         }
8647                     }
8648                 }
8649               if(nextNode!=startNode)
8650                 {
8651                   angle0=angleNext-M_PI;
8652                   if(angle0<-M_PI)
8653                     angle0+=2*M_PI;
8654                   prevNode=tmpOut.back();
8655                   tmpOut.push_back(nextNode);
8656                 }
8657             }
8658           std::vector<int> tmp3(2*(sz-1));
8659           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8660           std::copy(nodalConnBg+1,nodalConnEnd,it);
8661           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8662             {
8663               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8664               return false;
8665             }
8666           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8667             {
8668               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8669               return false;
8670             }
8671           else
8672             {
8673               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8674               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8675               return true;
8676             }
8677         }
8678       else
8679         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8680     }
8681   else
8682     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8683 }
8684
8685 /*!
8686  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8687  * 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.
8688  * 
8689  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8690  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8691  * \param [in,out] arr array in which the remove operation will be done.
8692  * \param [in,out] arrIndx array in the remove operation will modify
8693  * \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])
8694  * \return true if \b arr and \b arrIndx have been modified, false if not.
8695  */
8696 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8697 {
8698   if(!arrIndx || !arr)
8699     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8700   if(offsetForRemoval<0)
8701     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8702   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8703   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8704   int *arrIPtr=arrIndx->getPointer();
8705   *arrIPtr++=0;
8706   int previousArrI=0;
8707   const int *arrPtr=arr->getConstPointer();
8708   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8709   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8710     {
8711       if(*arrIPtr-previousArrI>offsetForRemoval)
8712         {
8713           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8714             {
8715               if(s.find(*work)==s.end())
8716                 arrOut.push_back(*work);
8717             }
8718         }
8719       previousArrI=*arrIPtr;
8720       *arrIPtr=(int)arrOut.size();
8721     }
8722   if(arr->getNumberOfTuples()==(int)arrOut.size())
8723     return false;
8724   arr->alloc((int)arrOut.size(),1);
8725   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8726   return true;
8727 }
8728
8729 /*!
8730  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8731  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8732  * The selection of extraction is done standardly in new2old format.
8733  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8734  *
8735  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8736  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8737  * \param [in] arrIn arr origin array from which the extraction will be done.
8738  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8739  * \param [out] arrOut the resulting array
8740  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8741  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8742  */
8743 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8744                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8745 {
8746   if(!arrIn || !arrIndxIn)
8747     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8748   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8749   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8750     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8751   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8752   const int *arrInPtr=arrIn->getConstPointer();
8753   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8754   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8755   if(nbOfGrps<0)
8756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8757   int maxSizeOfArr=arrIn->getNumberOfTuples();
8758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8760   arrIo->alloc((int)(sz+1),1);
8761   const int *idsIt=idsOfSelectBg;
8762   int *work=arrIo->getPointer();
8763   *work++=0;
8764   int lgth=0;
8765   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8766     {
8767       if(*idsIt>=0 && *idsIt<nbOfGrps)
8768         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8769       else
8770         {
8771           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8772           throw INTERP_KERNEL::Exception(oss.str().c_str());
8773         }
8774       if(lgth>=work[-1])
8775         *work=lgth;
8776       else
8777         {
8778           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8779           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8780           throw INTERP_KERNEL::Exception(oss.str().c_str());
8781         }
8782     }
8783   arro->alloc(lgth,1);
8784   work=arro->getPointer();
8785   idsIt=idsOfSelectBg;
8786   for(std::size_t i=0;i<sz;i++,idsIt++)
8787     {
8788       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8789         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8790       else
8791         {
8792           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8793           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8794           throw INTERP_KERNEL::Exception(oss.str().c_str());
8795         }
8796     }
8797   arrOut=arro.retn();
8798   arrIndexOut=arrIo.retn();
8799 }
8800
8801 /*!
8802  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8803  * 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 ).
8804  * The selection of extraction is done standardly in new2old format.
8805  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8806  *
8807  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8808  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8809  * \param [in] arrIn arr origin array from which the extraction will be done.
8810  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8811  * \param [out] arrOut the resulting array
8812  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8813  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8814  */
8815 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8816                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8817 {
8818   if(!arrIn || !arrIndxIn)
8819     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8820   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8821   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8822     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8823   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8824   const int *arrInPtr=arrIn->getConstPointer();
8825   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8826   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8827   if(nbOfGrps<0)
8828     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8829   int maxSizeOfArr=arrIn->getNumberOfTuples();
8830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8832   arrIo->alloc((int)(sz+1),1);
8833   int idsIt=idsOfSelectStart;
8834   int *work=arrIo->getPointer();
8835   *work++=0;
8836   int lgth=0;
8837   for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8838     {
8839       if(idsIt>=0 && idsIt<nbOfGrps)
8840         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8841       else
8842         {
8843           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8844           throw INTERP_KERNEL::Exception(oss.str().c_str());
8845         }
8846       if(lgth>=work[-1])
8847         *work=lgth;
8848       else
8849         {
8850           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8851           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8852           throw INTERP_KERNEL::Exception(oss.str().c_str());
8853         }
8854     }
8855   arro->alloc(lgth,1);
8856   work=arro->getPointer();
8857   idsIt=idsOfSelectStart;
8858   for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8859     {
8860       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8861         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8862       else
8863         {
8864           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8865           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8866           throw INTERP_KERNEL::Exception(oss.str().c_str());
8867         }
8868     }
8869   arrOut=arro.retn();
8870   arrIndexOut=arrIo.retn();
8871 }
8872
8873 /*!
8874  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8875  * 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
8876  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8877  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8878  *
8879  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8880  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8881  * \param [in] arrIn arr origin array from which the extraction will be done.
8882  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8883  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8884  * \param [in] srcArrIndex index array of \b srcArr
8885  * \param [out] arrOut the resulting array
8886  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8887  * 
8888  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8889  */
8890 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8891                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8892                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8893 {
8894   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8896   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8897   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8898   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8899   std::vector<bool> v(nbOfTuples,true);
8900   int offset=0;
8901   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8902   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8903   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8904     {
8905       if(*it>=0 && *it<nbOfTuples)
8906         {
8907           v[*it]=false;
8908           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8909         }
8910       else
8911         {
8912           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8913           throw INTERP_KERNEL::Exception(oss.str().c_str());
8914         }
8915     }
8916   srcArrIndexPtr=srcArrIndex->getConstPointer();
8917   arrIo->alloc(nbOfTuples+1,1);
8918   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8919   const int *arrInPtr=arrIn->getConstPointer();
8920   const int *srcArrPtr=srcArr->getConstPointer();
8921   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8922   int *arroPtr=arro->getPointer();
8923   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8924     {
8925       if(v[ii])
8926         {
8927           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8928           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8929         }
8930       else
8931         {
8932           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8933           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8934           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8935         }
8936     }
8937   arrOut=arro.retn();
8938   arrIndexOut=arrIo.retn();
8939 }
8940
8941 /*!
8942  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8943  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8944  *
8945  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8946  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8947  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8948  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8949  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8950  * \param [in] srcArrIndex index array of \b srcArr
8951  * 
8952  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8953  */
8954 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8955                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8956 {
8957   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8958     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8959   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8960   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8961   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8962   int *arrInOutPtr=arrInOut->getPointer();
8963   const int *srcArrPtr=srcArr->getConstPointer();
8964   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8965     {
8966       if(*it>=0 && *it<nbOfTuples)
8967         {
8968           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8969             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8970           else
8971             {
8972               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] !";
8973               throw INTERP_KERNEL::Exception(oss.str().c_str());
8974             }
8975         }
8976       else
8977         {
8978           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8979           throw INTERP_KERNEL::Exception(oss.str().c_str());
8980         }
8981     }
8982 }
8983
8984 /*!
8985  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8986  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8987  * 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]].
8988  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8989  * A negative value in \b arrIn means that it is ignored.
8990  * 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.
8991  * 
8992  * \param [in] arrIn arr origin array from which the extraction will be done.
8993  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8994  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8995  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8996  */
8997 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8998 {
8999   int seed=0,nbOfDepthPeelingPerformed=0;
9000   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9001 }
9002
9003 /*!
9004  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9005  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9006  * 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]].
9007  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9008  * A negative value in \b arrIn means that it is ignored.
9009  * 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.
9010  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9011  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9012  * \param [in] arrIn arr origin array from which the extraction will be done.
9013  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9014  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9015  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9016  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9017  * \sa MEDCouplingUMesh::partitionBySpreadZone
9018  */
9019 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9020 {
9021   nbOfDepthPeelingPerformed=0;
9022   if(!arrIndxIn)
9023     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9024   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9025   if(nbOfTuples<=0)
9026     {
9027       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9028       return ret;
9029     }
9030   //
9031   std::vector<bool> fetched(nbOfTuples,false);
9032   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9033 }
9034
9035 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)
9036 {
9037   nbOfDepthPeelingPerformed=0;
9038   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9039     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9040   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9041   std::vector<bool> fetched2(nbOfTuples,false);
9042   int i=0;
9043   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9044     {
9045       if(*seedElt>=0 && *seedElt<nbOfTuples)
9046         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9047       else
9048         { 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()); }
9049     }
9050   const int *arrInPtr=arrIn->getConstPointer();
9051   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9052   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9053   std::vector<int> idsToFetch1(seedBg,seedEnd);
9054   std::vector<int> idsToFetch2;
9055   std::vector<int> *idsToFetch=&idsToFetch1;
9056   std::vector<int> *idsToFetchOther=&idsToFetch2;
9057   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9058     {
9059       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9060         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9061           if(!fetched[*it2])
9062             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9063       std::swap(idsToFetch,idsToFetchOther);
9064       idsToFetchOther->clear();
9065       nbOfDepthPeelingPerformed++;
9066     }
9067   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9068   i=0;
9069   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9070   int *retPtr=ret->getPointer();
9071   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9072     if(*it)
9073       *retPtr++=i;
9074   return ret.retn();
9075 }
9076
9077 /*!
9078  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9079  * 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
9080  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9081  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9082  *
9083  * \param [in] start begin of set of ids of the input extraction (included)
9084  * \param [in] end end of set of ids of the input extraction (excluded)
9085  * \param [in] step step of the set of ids in range mode.
9086  * \param [in] arrIn arr origin array from which the extraction will be done.
9087  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9088  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9089  * \param [in] srcArrIndex index array of \b srcArr
9090  * \param [out] arrOut the resulting array
9091  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9092  * 
9093  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9094  */
9095 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9096                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9097                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9098 {
9099   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9100     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9101   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9102   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9103   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9104   int offset=0;
9105   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9106   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9107   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9108   int it=start;
9109   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9110     {
9111       if(it>=0 && it<nbOfTuples)
9112         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9113       else
9114         {
9115           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9116           throw INTERP_KERNEL::Exception(oss.str().c_str());
9117         }
9118     }
9119   srcArrIndexPtr=srcArrIndex->getConstPointer();
9120   arrIo->alloc(nbOfTuples+1,1);
9121   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9122   const int *arrInPtr=arrIn->getConstPointer();
9123   const int *srcArrPtr=srcArr->getConstPointer();
9124   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9125   int *arroPtr=arro->getPointer();
9126   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9127     {
9128       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9129       if(pos<0)
9130         {
9131           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9132           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9133         }
9134       else
9135         {
9136           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9137           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9138         }
9139     }
9140   arrOut=arro.retn();
9141   arrIndexOut=arrIo.retn();
9142 }
9143
9144 /*!
9145  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9146  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9147  *
9148  * \param [in] start begin of set of ids of the input extraction (included)
9149  * \param [in] end end of set of ids of the input extraction (excluded)
9150  * \param [in] step step of the set of ids in range mode.
9151  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9152  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9153  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9154  * \param [in] srcArrIndex index array of \b srcArr
9155  * 
9156  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9157  */
9158 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9159                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9160 {
9161   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9162     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9163   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9164   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9165   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9166   int *arrInOutPtr=arrInOut->getPointer();
9167   const int *srcArrPtr=srcArr->getConstPointer();
9168   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9169   int it=start;
9170   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9171     {
9172       if(it>=0 && it<nbOfTuples)
9173         {
9174           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9175             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9176           else
9177             {
9178               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9179               throw INTERP_KERNEL::Exception(oss.str().c_str());
9180             }
9181         }
9182       else
9183         {
9184           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9185           throw INTERP_KERNEL::Exception(oss.str().c_str());
9186         }
9187     }
9188 }
9189
9190 /*!
9191  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9192  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9193  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9194  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9195  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9196  * 
9197  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9198  */
9199 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9200 {
9201   checkFullyDefined();
9202   int mdim=getMeshDimension();
9203   int spaceDim=getSpaceDimension();
9204   if(mdim!=spaceDim)
9205     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9206   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9207   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9208   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9209   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9210   ret->setCoords(getCoords());
9211   ret->allocateCells((int)partition.size());
9212   //
9213   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9214     {
9215       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9216       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9217       switch(mdim)
9218         {
9219         case 2:
9220           cell=tmp->buildUnionOf2DMesh();
9221           break;
9222         case 3:
9223           cell=tmp->buildUnionOf3DMesh();
9224           break;
9225         default:
9226           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9227         }
9228       
9229       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9230     }
9231   //
9232   ret->finishInsertingCells();
9233   return ret.retn();
9234 }
9235
9236 /*!
9237  * This method partitions \b this into contiguous zone.
9238  * This method only needs a well defined connectivity. Coordinates are not considered here.
9239  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9240  */
9241 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9242 {
9243   //#if 0
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   //#endif
9264 #if 0
9265   int nbOfCellsCur=getNumberOfCells();
9266   DataArrayInt *neigh=0,*neighI=0;
9267   computeNeighborsOfCells(neigh,neighI);
9268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9269   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9270   std::vector<DataArrayInt *> ret;
9271   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9272   while(nbOfCellsCur>0)
9273     {
9274       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9275       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9276       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9277       ret2.push_back(tmp2);  ret.push_back(tmp2);
9278       nbOfCellsCur=tmp3->getNumberOfTuples();
9279       if(nbOfCellsCur>0)
9280         {
9281           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9282           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9283           neighAuto=neigh;
9284           neighIAuto=neighI;
9285           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9286           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9287         }
9288     }
9289   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9290     (*it)->incrRef();
9291   return ret;
9292 #endif
9293 }
9294
9295 /*!
9296  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9297  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9298  *
9299  * \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.
9300  * \return a newly allocated DataArrayInt to be managed by the caller.
9301  * \throw In case of \a code has not the right format (typically of size 3*n)
9302  */
9303 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9304 {
9305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9306   std::size_t nb=code.size()/3;
9307   if(code.size()%3!=0)
9308     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9309   ret->alloc((int)nb,2);
9310   int *retPtr=ret->getPointer();
9311   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9312     {
9313       retPtr[0]=code[3*i+2];
9314       retPtr[1]=code[3*i+2]+code[3*i+1];
9315     }
9316   return ret.retn();
9317 }
9318
9319 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9320                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9321 {
9322   if(mesh)
9323     {
9324       mesh->incrRef();
9325       _nb_cell=mesh->getNumberOfCells();
9326     }
9327 }
9328
9329 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9330 {
9331   if(_mesh)
9332     _mesh->decrRef();
9333   if(_own_cell)
9334     delete _cell;
9335 }
9336
9337 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9338                                                                                                                                _own_cell(false),_cell_id(bg-1),
9339                                                                                                                                _nb_cell(end)
9340 {
9341   if(mesh)
9342     mesh->incrRef();
9343 }
9344
9345 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9346 {
9347   _cell_id++;
9348   if(_cell_id<_nb_cell)
9349     {
9350       _cell->next();
9351       return _cell;
9352     }
9353   else
9354     return 0;
9355 }
9356
9357 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9358 {
9359   if(_mesh)
9360     _mesh->incrRef();
9361 }
9362
9363 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9364 {
9365   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9366 }
9367
9368 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9369 {
9370   if(_mesh)
9371     _mesh->decrRef();
9372 }
9373
9374 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9375                                                                                                                                                                   _itc(itc),
9376                                                                                                                                                                   _bg(bg),_end(end)
9377 {
9378   if(_mesh)
9379     _mesh->incrRef();
9380 }
9381
9382 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9383 {
9384   if(_mesh)
9385     _mesh->decrRef();
9386 }
9387
9388 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9389 {
9390   return _type;
9391 }
9392
9393 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9394 {
9395   return _end-_bg;
9396 }
9397
9398 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9399 {
9400   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9401 }
9402
9403 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9404 {
9405   if(mesh)
9406     {
9407       mesh->incrRef();
9408       _nb_cell=mesh->getNumberOfCells();
9409     }
9410 }
9411
9412 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9413 {
9414   if(_mesh)
9415     _mesh->decrRef();
9416   delete _cell;
9417 }
9418
9419 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9420 {
9421   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9422   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9423   if(_cell_id<_nb_cell)
9424     {
9425       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9426       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9427       int startId=_cell_id;
9428       _cell_id+=nbOfElems;
9429       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9430     }
9431   else
9432     return 0;
9433 }
9434
9435 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9436 {
9437   if(mesh)
9438     {
9439       _conn=mesh->getNodalConnectivity()->getPointer();
9440       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9441     }
9442 }
9443
9444 void MEDCouplingUMeshCell::next()
9445 {
9446   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9447     {
9448       _conn+=_conn_lgth;
9449       _conn_indx++;
9450     }
9451   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9452 }
9453
9454 std::string MEDCouplingUMeshCell::repr() const
9455 {
9456   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9457     {
9458       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9459       oss << " : ";
9460       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9461       return oss.str();
9462     }
9463   else
9464     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9465 }
9466
9467 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9468 {
9469   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9470     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9471   else
9472     return INTERP_KERNEL::NORM_ERROR;
9473 }
9474
9475 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9476 {
9477   lgth=_conn_lgth;
9478   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9479     return _conn;
9480   else
9481     return 0;
9482 }