Salome HOME
abstraction of MEDCouplingPointSet::getBoundingBoxForBBTree
[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   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3881   const double *bbox(bboxArr->begin());
3882   switch(spaceDim)
3883     {
3884     case 3:
3885       {
3886         BBTreeDst<3> myTree(bbox,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,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   eltsIndex.resize(nbOfPoints+1);
4160   eltsIndex[0]=0;
4161   elts.clear();
4162   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4163   const double *bbox(bboxArr->begin());
4164   int nbOfCells=getNumberOfCells();
4165   const int *conn=_nodal_connec->getConstPointer();
4166   const int *connI=_nodal_connec_index->getConstPointer();
4167   double bb[2*SPACEDIM];
4168   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4169   for(int i=0;i<nbOfPoints;i++)
4170     {
4171       eltsIndex[i+1]=eltsIndex[i];
4172       for(int j=0;j<SPACEDIM;j++)
4173         {
4174           bb[2*j]=pos[SPACEDIM*i+j];
4175           bb[2*j+1]=pos[SPACEDIM*i+j];
4176         }
4177       std::vector<int> candidates;
4178       myTree.getIntersectingElems(bb,candidates);
4179       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4180         {
4181           int sz=connI[(*iter)+1]-connI[*iter]-1;
4182           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4183                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4184                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4185             {
4186               eltsIndex[i+1]++;
4187               elts.push_back(*iter);
4188             }
4189         }
4190     }
4191 }
4192 /*!
4193  * Finds cells in contact with several balls (i.e. points with precision).
4194  * This method is an extension of getCellContainingPoint() and
4195  * getCellsContainingPoint() for the case of multiple points.
4196  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4197  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4198  *         this->getSpaceDimension() * \a nbOfPoints 
4199  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4200  *  \param [in] eps - radius of balls (i.e. the precision).
4201  *  \param [in,out] elts - vector returning ids of found cells.
4202  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4203  *         dividing cell ids in \a elts into groups each referring to one
4204  *         point. Its every element (except the last one) is an index pointing to the
4205  *         first id of a group of cells. For example cells in contact with the *i*-th
4206  *         point are described by following range of indices:
4207  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4208  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4209  *         Number of cells in contact with the *i*-th point is
4210  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4211  *  \throw If the coordinates array is not set.
4212  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4213  *
4214  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4215  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4216  */
4217 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4218                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4219 {
4220   int spaceDim=getSpaceDimension();
4221   int mDim=getMeshDimension();
4222   if(spaceDim==3)
4223     {
4224       if(mDim==3)
4225         {
4226           const double *coords=_coords->getConstPointer();
4227           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4228         }
4229       /*else if(mDim==2)
4230         {
4231           
4232         }*/
4233       else
4234         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4235     }
4236   else if(spaceDim==2)
4237     {
4238       if(mDim==2)
4239         {
4240           const double *coords=_coords->getConstPointer();
4241           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4242         }
4243       else
4244         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4245     }
4246   else if(spaceDim==1)
4247     {
4248       if(mDim==1)
4249         {
4250           const double *coords=_coords->getConstPointer();
4251           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4252         }
4253       else
4254         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4255     }
4256   else
4257     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4258 }
4259
4260 /*!
4261  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4262  * least two its edges intersect each other anywhere except their extremities. An
4263  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4264  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4265  *         cleared before filling in.
4266  *  \param [in] eps - precision.
4267  *  \throw If \a this->getMeshDimension() != 2.
4268  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4269  */
4270 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4271 {
4272   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4273   if(getMeshDimension()!=2)
4274     throw INTERP_KERNEL::Exception(msg);
4275   int spaceDim=getSpaceDimension();
4276   if(spaceDim!=2 && spaceDim!=3)
4277     throw INTERP_KERNEL::Exception(msg);
4278   const int *conn=_nodal_connec->getConstPointer();
4279   const int *connI=_nodal_connec_index->getConstPointer();
4280   int nbOfCells=getNumberOfCells();
4281   std::vector<double> cell2DinS2;
4282   for(int i=0;i<nbOfCells;i++)
4283     {
4284       int offset=connI[i];
4285       int nbOfNodesForCell=connI[i+1]-offset-1;
4286       if(nbOfNodesForCell<=3)
4287         continue;
4288       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4289       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4290       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4291         cells.push_back(i);
4292       cell2DinS2.clear();
4293     }
4294 }
4295
4296 /*!
4297  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4298  *
4299  * This method expects that space dimension is equal to 2 and mesh dimension is equal to 2 too. If it is not the case an INTERP_KERNEL::Exception will be thrown.
4300  * This method works only for linear 2D cells. If there is any of non linear cells (INTERP_KERNEL::NORM_QUAD8 for example) an INTERP_KERNEL::Exception will be thrown too.
4301  * 
4302  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4303  * This convex envelop is computed using Jarvis march algorithm.
4304  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4305  * Only connectivity of some cells could be modified if those cells were not representing a convex envelop. If a cell already equals its convex envelop (regardless orientation)
4306  * its connectivity will remain unchanged. If the computation leads to a modification of nodal connectivity of a cell its geometric type will be modified to INTERP_KERNEL::NORM_POLYGON.
4307  *
4308  * \return a newly allocated array containing cellIds that have been modified if any. If no cells have been impacted by this method NULL is returned.
4309  */
4310 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4311 {
4312   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4314   checkFullyDefined();
4315   const double *coords=getCoords()->getConstPointer();
4316   int nbOfCells=getNumberOfCells();
4317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4318   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4320   int *workIndexOut=nodalConnecIndexOut->getPointer();
4321   *workIndexOut=0;
4322   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4323   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4324   std::set<INTERP_KERNEL::NormalizedCellType> types;
4325   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4326   isChanged->alloc(0,1);
4327   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4328     {
4329       int pos=nodalConnecOut->getNumberOfTuples();
4330       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4331         isChanged->pushBackSilent(i);
4332       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4333       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4334     }
4335   if(isChanged->empty())
4336     return 0;
4337   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4338   _types=types;
4339   return isChanged.retn();
4340 }
4341
4342 /*!
4343  * This method is \b NOT const because it can modify \a this.
4344  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4345  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4346  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4347  * \b 1 for translation and rotation around point of 'mesh1D'.
4348  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4349  */
4350 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4351 {
4352   checkFullyDefined();
4353   mesh1D->checkFullyDefined();
4354   if(!mesh1D->isContiguous1D())
4355     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4356   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4357     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4358   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4359     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4360   if(mesh1D->getMeshDimension()!=1)
4361     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4362   bool isQuad=false;
4363   if(isPresenceOfQuadratic())
4364     {
4365       if(mesh1D->isFullyQuadratic())
4366         isQuad=true;
4367       else
4368         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4369     }
4370   zipCoords();
4371   int oldNbOfNodes=getNumberOfNodes();
4372   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4373   switch(policy)
4374     {
4375     case 0:
4376       {
4377         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4378         break;
4379       }
4380     case 1:
4381       {
4382         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4383         break;
4384       }
4385     default:
4386       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4387     }
4388   setCoords(newCoords);
4389   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4390   updateTime();
4391   return ret.retn();
4392 }
4393
4394 /*!
4395  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4396  * If it is not the case an exception will be thrown.
4397  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4398  * intersection of plane defined by ('origin','vec').
4399  * This method has one in/out parameter : 'cut3DCurve'.
4400  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4401  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4402  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4403  * This method will throw an exception if \a this contains a non linear segment.
4404  */
4405 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4406 {
4407   checkFullyDefined();
4408   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4409     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4410   int ncells=getNumberOfCells();
4411   int nnodes=getNumberOfNodes();
4412   double vec2[3],vec3[3],vec4[3];
4413   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4414   if(normm<1e-6)
4415     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4416   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4417   const int *conn=_nodal_connec->getConstPointer();
4418   const int *connI=_nodal_connec_index->getConstPointer();
4419   const double *coo=_coords->getConstPointer();
4420   std::vector<double> addCoo;
4421   for(int i=0;i<ncells;i++)
4422     {
4423       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4424         {
4425           if(cut3DCurve[i]==-2)
4426             {
4427               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4428               vec3[0]=coo[3*endd]-coo[3*st]; vec3[1]=coo[3*endd+1]-coo[3*st+1]; vec3[2]=coo[3*endd+2]-coo[3*st+2];
4429               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4430               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4431               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4432                 {
4433                   const double *st2=coo+3*st;
4434                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4435                   double pos=-(vec4[0]*vec2[0]+vec4[1]*vec2[1]+vec4[2]*vec2[2])/((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2]));
4436                   if(pos>eps && pos<1-eps)
4437                     {
4438                       int nNode=((int)addCoo.size())/3;
4439                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4440                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4441                       cut3DCurve[i]=nnodes+nNode;
4442                     }
4443                 }
4444             }
4445         }
4446       else
4447         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4448     }
4449   if(!addCoo.empty())
4450     {
4451       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4452       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4453       coo2->alloc(newNbOfNodes,3);
4454       double *tmp=coo2->getPointer();
4455       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4456       std::copy(addCoo.begin(),addCoo.end(),tmp);
4457       DataArrayDouble::SetArrayIn(coo2,_coords);
4458     }
4459 }
4460
4461 /*!
4462  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4463  * \param mesh1D is the input 1D mesh used for translation computation.
4464  * \return newCoords new coords filled by this method. 
4465  */
4466 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4467 {
4468   int oldNbOfNodes=getNumberOfNodes();
4469   int nbOf1DCells=mesh1D->getNumberOfCells();
4470   int spaceDim=getSpaceDimension();
4471   DataArrayDouble *ret=DataArrayDouble::New();
4472   std::vector<bool> isQuads;
4473   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4474   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4475   double *retPtr=ret->getPointer();
4476   const double *coords=getCoords()->getConstPointer();
4477   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4478   std::vector<int> v;
4479   std::vector<double> c;
4480   double vec[3];
4481   v.reserve(3);
4482   c.reserve(6);
4483   for(int i=0;i<nbOf1DCells;i++)
4484     {
4485       v.resize(0);
4486       mesh1D->getNodeIdsOfCell(i,v);
4487       c.resize(0);
4488       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4489       mesh1D->getCoordinatesOfNode(v[0],c);
4490       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4491       for(int j=0;j<oldNbOfNodes;j++)
4492         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4493       if(isQuad)
4494         {
4495           c.resize(0);
4496           mesh1D->getCoordinatesOfNode(v[1],c);
4497           mesh1D->getCoordinatesOfNode(v[0],c);
4498           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4499           for(int j=0;j<oldNbOfNodes;j++)
4500             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4501         }
4502     }
4503   ret->copyStringInfoFrom(*getCoords());
4504   return ret;
4505 }
4506
4507 /*!
4508  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4509  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4510  * \return newCoords new coords filled by this method. 
4511  */
4512 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4513 {
4514   if(mesh1D->getSpaceDimension()==2)
4515     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4516   if(mesh1D->getSpaceDimension()==3)
4517     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4518   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4519 }
4520
4521 /*!
4522  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4523  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4524  * \return newCoords new coords filled by this method. 
4525  */
4526 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4527 {
4528   if(isQuad)
4529     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4530   int oldNbOfNodes=getNumberOfNodes();
4531   int nbOf1DCells=mesh1D->getNumberOfCells();
4532   if(nbOf1DCells<2)
4533     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4534   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4535   int nbOfLevsInVec=nbOf1DCells+1;
4536   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4537   double *retPtr=ret->getPointer();
4538   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4539   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4540   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4541   tmp->setCoords(tmp2);
4542   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4543   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4544   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4545   for(int i=1;i<nbOfLevsInVec;i++)
4546     {
4547       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4548       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4549       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4550       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4551       tmp->translate(vec);
4552       double tmp3[2],radius,alpha,alpha0;
4553       const double *p0=i+1<nbOfLevsInVec?begin:third;
4554       const double *p1=i+1<nbOfLevsInVec?end:begin;
4555       const double *p2=i+1<nbOfLevsInVec?third:end;
4556       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4557       double cosangle=i+1<nbOfLevsInVec?(p0[0]-tmp3[0])*(p1[0]-tmp3[0])+(p0[1]-tmp3[1])*(p1[1]-tmp3[1]):(p2[0]-tmp3[0])*(p1[0]-tmp3[0])+(p2[1]-tmp3[1])*(p1[1]-tmp3[1]);
4558       double angle=acos(cosangle/(radius*radius));
4559       tmp->rotate(end,0,angle);
4560       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4561     }
4562   return ret.retn();
4563 }
4564
4565 /*!
4566  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4567  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4568  * \return newCoords new coords filled by this method. 
4569  */
4570 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4571 {
4572   if(isQuad)
4573     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4574   int oldNbOfNodes=getNumberOfNodes();
4575   int nbOf1DCells=mesh1D->getNumberOfCells();
4576   if(nbOf1DCells<2)
4577     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4578   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4579   int nbOfLevsInVec=nbOf1DCells+1;
4580   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4581   double *retPtr=ret->getPointer();
4582   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4583   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4584   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4585   tmp->setCoords(tmp2);
4586   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4587   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4588   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4589   for(int i=1;i<nbOfLevsInVec;i++)
4590     {
4591       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4592       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4593       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4594       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4595       tmp->translate(vec);
4596       double tmp3[2],radius,alpha,alpha0;
4597       const double *p0=i+1<nbOfLevsInVec?begin:third;
4598       const double *p1=i+1<nbOfLevsInVec?end:begin;
4599       const double *p2=i+1<nbOfLevsInVec?third:end;
4600       double vecPlane[3]={
4601         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4602         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4603         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4604       };
4605       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4606       if(norm>1.e-7)
4607         {
4608           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4609           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4610           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4611           double s2=norm2;
4612           double c2=cos(asin(s2));
4613           double m[3][3]={
4614             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4615             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4616             {-vec2[1]*s2, vec2[0]*s2, c2}
4617           };
4618           double p0r[3]={m[0][0]*p0[0]+m[0][1]*p0[1]+m[0][2]*p0[2], m[1][0]*p0[0]+m[1][1]*p0[1]+m[1][2]*p0[2], m[2][0]*p0[0]+m[2][1]*p0[1]+m[2][2]*p0[2]};
4619           double p1r[3]={m[0][0]*p1[0]+m[0][1]*p1[1]+m[0][2]*p1[2], m[1][0]*p1[0]+m[1][1]*p1[1]+m[1][2]*p1[2], m[2][0]*p1[0]+m[2][1]*p1[1]+m[2][2]*p1[2]};
4620           double p2r[3]={m[0][0]*p2[0]+m[0][1]*p2[1]+m[0][2]*p2[2], m[1][0]*p2[0]+m[1][1]*p2[1]+m[1][2]*p2[2], m[2][0]*p2[0]+m[2][1]*p2[1]+m[2][2]*p2[2]};
4621           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4622           double cosangle=i+1<nbOfLevsInVec?(p0r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p0r[1]-tmp3[1])*(p1r[1]-tmp3[1]):(p2r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p2r[1]-tmp3[1])*(p1r[1]-tmp3[1]);
4623           double angle=acos(cosangle/(radius*radius));
4624           tmp->rotate(end,vecPlane,angle);
4625           
4626         }
4627       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4628     }
4629   return ret.retn();
4630 }
4631
4632 /*!
4633  * This method is private because not easy to use for end user. This method is const contrary to
4634  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4635  * the coords sorted slice by slice.
4636  * \param isQuad specifies presence of quadratic cells.
4637  */
4638 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4639 {
4640   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4641   int nbOf2DCells=getNumberOfCells();
4642   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4643   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4644   const int *conn=_nodal_connec->getConstPointer();
4645   const int *connI=_nodal_connec_index->getConstPointer();
4646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4648   newConnI->alloc(nbOf3DCells+1,1);
4649   int *newConnIPtr=newConnI->getPointer();
4650   *newConnIPtr++=0;
4651   std::vector<int> newc;
4652   for(int j=0;j<nbOf2DCells;j++)
4653     {
4654       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4655       *newConnIPtr++=(int)newc.size();
4656     }
4657   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4658   int *newConnPtr=newConn->getPointer();
4659   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4660   newConnIPtr=newConnI->getPointer();
4661   for(int iz=0;iz<nbOf1DCells;iz++)
4662     {
4663       if(iz!=0)
4664         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4665       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4666         {
4667           int icell=(int)(iter-newc.begin());
4668           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4669             {
4670               if(*iter!=-1)
4671                 *newConnPtr=(*iter)+iz*deltaPerLev;
4672               else
4673                 *newConnPtr=-1;
4674             }
4675           else
4676             *newConnPtr=(*iter);
4677         }
4678     }
4679   ret->setConnectivity(newConn,newConnI,true);
4680   ret->setCoords(getCoords());
4681   return ret;
4682 }
4683
4684 /*!
4685  * Checks if \a this mesh is constituted by only quadratic cells.
4686  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4687  *  \throw If the coordinates array is not set.
4688  *  \throw If the nodal connectivity of cells is not defined.
4689  */
4690 bool MEDCouplingUMesh::isFullyQuadratic() const
4691 {
4692   checkFullyDefined();
4693   bool ret=true;
4694   int nbOfCells=getNumberOfCells();
4695   for(int i=0;i<nbOfCells && ret;i++)
4696     {
4697       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4698       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4699       ret=cm.isQuadratic();
4700     }
4701   return ret;
4702 }
4703
4704 /*!
4705  * Checks if \a this mesh includes any quadratic cell.
4706  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4707  *  \throw If the coordinates array is not set.
4708  *  \throw If the nodal connectivity of cells is not defined.
4709  */
4710 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4711 {
4712   checkFullyDefined();
4713   bool ret=false;
4714   int nbOfCells=getNumberOfCells();
4715   for(int i=0;i<nbOfCells && !ret;i++)
4716     {
4717       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4718       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4719       ret=cm.isQuadratic();
4720     }
4721   return ret;
4722 }
4723
4724 /*!
4725  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4726  * this mesh, it remains unchanged.
4727  *  \throw If the coordinates array is not set.
4728  *  \throw If the nodal connectivity of cells is not defined.
4729  */
4730 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4731 {
4732   checkFullyDefined();
4733   int nbOfCells=getNumberOfCells();
4734   int delta=0;
4735   const int *iciptr=_nodal_connec_index->getConstPointer();
4736   for(int i=0;i<nbOfCells;i++)
4737     {
4738       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4739       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4740       if(cm.isQuadratic())
4741         {
4742           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4743           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4744           if(!cml.isDynamic())
4745             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4746           else
4747             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4748         }
4749     }
4750   if(delta==0)
4751     return ;
4752   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4754   const int *icptr=_nodal_connec->getConstPointer();
4755   newConn->alloc(getMeshLength()-delta,1);
4756   newConnI->alloc(nbOfCells+1,1);
4757   int *ocptr=newConn->getPointer();
4758   int *ociptr=newConnI->getPointer();
4759   *ociptr=0;
4760   _types.clear();
4761   for(int i=0;i<nbOfCells;i++,ociptr++)
4762     {
4763       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4764       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4765       if(!cm.isQuadratic())
4766         {
4767           _types.insert(type);
4768           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4769           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4770         }
4771       else
4772         {
4773           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4774           _types.insert(typel);
4775           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4776           int newNbOfNodes=cml.getNumberOfNodes();
4777           if(cml.isDynamic())
4778             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4779           *ocptr++=(int)typel;
4780           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4781           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4782         }
4783     }
4784   setConnectivity(newConn,newConnI,false);
4785 }
4786
4787 /*!
4788  * This method converts all linear cell in \a this to quadratic one.
4789  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4790  * type of cells expected. For example INTERP_KERNEL::NORM_TRI3 can be converted to INTERP_KERNEL::NORM_TRI6 if \a conversionType is equal to 0 (the default)
4791  * or to INTERP_KERNEL::NORM_TRI7 if \a conversionType is equal to 1. All non linear cells and polyhedron in \a this are let untouched.
4792  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4793  * end of the existing coordinates.
4794  * 
4795  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4796  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4797  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4798  * 
4799  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4800  *
4801  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4802  */
4803 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4804 {
4805   DataArrayInt *conn=0,*connI=0;
4806   DataArrayDouble *coords=0;
4807   std::set<INTERP_KERNEL::NormalizedCellType> types;
4808   checkFullyDefined();
4809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4810   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4811   int meshDim=getMeshDimension();
4812   switch(conversionType)
4813     {
4814     case 0:
4815       switch(meshDim)
4816         {
4817         case 1:
4818           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4819           connSafe=conn; connISafe=connI; coordsSafe=coords;
4820           break;
4821         case 2:
4822           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4823           connSafe=conn; connISafe=connI; coordsSafe=coords;
4824           break;
4825         case 3:
4826           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4827           connSafe=conn; connISafe=connI; coordsSafe=coords;
4828           break;
4829         default:
4830           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4831         }
4832       break;
4833     case 1:
4834       {
4835         switch(meshDim)
4836         {
4837         case 1:
4838           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4839           connSafe=conn; connISafe=connI; coordsSafe=coords;
4840           break;
4841         case 2:
4842           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4843           connSafe=conn; connISafe=connI; coordsSafe=coords;
4844           break;
4845         case 3:
4846           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4847           connSafe=conn; connISafe=connI; coordsSafe=coords;
4848           break;
4849         default:
4850           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4851         }
4852         break;
4853       }
4854     default:
4855       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4856     }
4857   setConnectivity(connSafe,connISafe,false);
4858   _types=types;
4859   setCoords(coordsSafe);
4860   return ret.retn();
4861 }
4862
4863 /*!
4864  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4865  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4866  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4867  */
4868 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4869 {
4870   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4871   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4872   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4873   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4874   int nbOfCells=getNumberOfCells();
4875   int nbOfNodes=getNumberOfNodes();
4876   const int *cPtr=_nodal_connec->getConstPointer();
4877   const int *icPtr=_nodal_connec_index->getConstPointer();
4878   int lastVal=0,offset=nbOfNodes;
4879   for(int i=0;i<nbOfCells;i++,icPtr++)
4880     {
4881       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4882       if(type==INTERP_KERNEL::NORM_SEG2)
4883         {
4884           types.insert(INTERP_KERNEL::NORM_SEG3);
4885           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4886           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4887           newConn->pushBackSilent(offset++);
4888           lastVal+=4;
4889           newConnI->pushBackSilent(lastVal);
4890           ret->pushBackSilent(i);
4891         }
4892       else
4893         {
4894           types.insert(type);
4895           lastVal+=(icPtr[1]-icPtr[0]);
4896           newConnI->pushBackSilent(lastVal);
4897           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4898         }
4899     }
4900   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4901   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4902   return ret.retn();
4903 }
4904
4905 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4906 {
4907   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4908   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4909   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4910   //
4911   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4912   DataArrayInt *conn1D=0,*conn1DI=0;
4913   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4914   DataArrayDouble *coordsTmp=0;
4915   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4916   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4917   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4918   const int *c1DPtr=conn1D->begin();
4919   const int *c1DIPtr=conn1DI->begin();
4920   int nbOfCells=getNumberOfCells();
4921   const int *cPtr=_nodal_connec->getConstPointer();
4922   const int *icPtr=_nodal_connec_index->getConstPointer();
4923   int lastVal=0;
4924   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4925     {
4926       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4927       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4928       if(!cm.isQuadratic())
4929         {
4930           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4931           types.insert(typ2); newConn->pushBackSilent(typ2);
4932           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4933           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4934             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4935           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4936           newConnI->pushBackSilent(lastVal);
4937           ret->pushBackSilent(i);
4938         }
4939       else
4940         {
4941           types.insert(typ);
4942           lastVal+=(icPtr[1]-icPtr[0]);
4943           newConnI->pushBackSilent(lastVal);
4944           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4945         }
4946     }
4947   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4948   return ret.retn();
4949 }
4950
4951 /*!
4952  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4953  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4954  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4955  */
4956 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4957 {
4958   
4959   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4960   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4961   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4962 }
4963
4964 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4965 {
4966   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4967   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4968   //
4969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4971   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4972   //
4973   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4974   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4975   DataArrayInt *conn1D=0,*conn1DI=0;
4976   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4977   DataArrayDouble *coordsTmp=0;
4978   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4979   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4980   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4981   const int *c1DPtr=conn1D->begin();
4982   const int *c1DIPtr=conn1DI->begin();
4983   int nbOfCells=getNumberOfCells();
4984   const int *cPtr=_nodal_connec->getConstPointer();
4985   const int *icPtr=_nodal_connec_index->getConstPointer();
4986   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4987   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4988     {
4989       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4990       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4991       if(!cm.isQuadratic())
4992         {
4993           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4994           types.insert(typ2); newConn->pushBackSilent(typ2);
4995           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4996           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4997             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4998           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4999           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5000           newConnI->pushBackSilent(lastVal);
5001           ret->pushBackSilent(i);
5002         }
5003       else
5004         {
5005           types.insert(typ);
5006           lastVal+=(icPtr[1]-icPtr[0]);
5007           newConnI->pushBackSilent(lastVal);
5008           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5009         }
5010     }
5011   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5012   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5013   return ret.retn();
5014 }
5015
5016 /*!
5017  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5018  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5019  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5020  */
5021 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5022 {
5023   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5024   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5025   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5026 }
5027
5028 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5029 {
5030   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5031   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5032   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5033   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5034   //
5035   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5036   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5037   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5038   //
5039   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5040   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5041   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5042   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5043   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5044   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5045   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5046   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5047   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5048   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5049   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5050   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5051   int nbOfCells=getNumberOfCells();
5052   const int *cPtr=_nodal_connec->getConstPointer();
5053   const int *icPtr=_nodal_connec_index->getConstPointer();
5054   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5055   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5056     {
5057       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5058       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5059       if(!cm.isQuadratic())
5060         {
5061           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5062           if(typ2==INTERP_KERNEL::NORM_ERROR)
5063             {
5064               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5065               throw INTERP_KERNEL::Exception(oss.str().c_str());
5066             }
5067           types.insert(typ2); newConn->pushBackSilent(typ2);
5068           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5069           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5070             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5071           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5072             {
5073               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5074               int tmpPos=newConn->getNumberOfTuples();
5075               newConn->pushBackSilent(nodeId2);
5076               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5077             }
5078           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5079           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5080           newConnI->pushBackSilent(lastVal);
5081           ret->pushBackSilent(i);
5082         }
5083       else
5084         {
5085           types.insert(typ);
5086           lastVal+=(icPtr[1]-icPtr[0]);
5087           newConnI->pushBackSilent(lastVal);
5088           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5089         }
5090     }
5091   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5092   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5093   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5094   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5095   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5096   int *c=newConn->getPointer();
5097   const int *cI(newConnI->begin());
5098   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5099     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5100   offset=coordsTmp2Safe->getNumberOfTuples();
5101   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5102     c[cI[(*elt)+1]-1]+=offset;
5103   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5104   return ret.retn();
5105 }
5106
5107 /*!
5108  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5109  * so that the number of cells remains the same. Quadratic faces are converted to
5110  * polygons. This method works only for 2D meshes in
5111  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5112  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5113  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5114  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5115  *         a polylinized edge constituting the input polygon.
5116  *  \throw If the coordinates array is not set.
5117  *  \throw If the nodal connectivity of cells is not defined.
5118  *  \throw If \a this->getMeshDimension() != 2.
5119  *  \throw If \a this->getSpaceDimension() != 2.
5120  */
5121 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5122 {
5123   checkFullyDefined();
5124   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5125     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5126   double epsa=fabs(eps);
5127   if(epsa<std::numeric_limits<double>::min())
5128     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5129   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5131   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5132   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5133   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5134   revDesc1=0; revDescIndx1=0;
5135   mDesc->tessellate2DCurve(eps);
5136   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5137   setCoords(mDesc->getCoords());
5138 }
5139
5140 /*!
5141  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5142  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5143  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5144  *         a sub-divided edge.
5145  *  \throw If the coordinates array is not set.
5146  *  \throw If the nodal connectivity of cells is not defined.
5147  *  \throw If \a this->getMeshDimension() != 1.
5148  *  \throw If \a this->getSpaceDimension() != 2.
5149  */
5150 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5151 {
5152   checkFullyDefined();
5153   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5154     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5155   double epsa=fabs(eps);
5156   if(epsa<std::numeric_limits<double>::min())
5157     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5158   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5159   int nbCells=getNumberOfCells();
5160   int nbNodes=getNumberOfNodes();
5161   const int *conn=_nodal_connec->getConstPointer();
5162   const int *connI=_nodal_connec_index->getConstPointer();
5163   const double *coords=_coords->getConstPointer();
5164   std::vector<double> addCoo;
5165   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5166   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5167   newConnI->alloc(nbCells+1,1);
5168   int *newConnIPtr=newConnI->getPointer();
5169   *newConnIPtr=0;
5170   int tmp1[3];
5171   INTERP_KERNEL::Node *tmp2[3];
5172   std::set<INTERP_KERNEL::NormalizedCellType> types;
5173   for(int i=0;i<nbCells;i++,newConnIPtr++)
5174     {
5175       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5176       if(cm.isQuadratic())
5177         {//assert(connI[i+1]-connI[i]-1==3)
5178           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5179           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5180           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5181           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5182           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5183           if(eac)
5184             {
5185               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5186               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5187               delete eac;
5188               newConnIPtr[1]=(int)newConn.size();
5189             }
5190           else
5191             {
5192               types.insert(INTERP_KERNEL::NORM_SEG2);
5193               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5194               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5195               newConnIPtr[1]=newConnIPtr[0]+3;
5196             }
5197         }
5198       else
5199         {
5200           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5201           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5202           newConnIPtr[1]=newConnIPtr[0]+3;
5203         }
5204     }
5205   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5206     return ;
5207   _types=types;
5208   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5210   newConnArr->alloc((int)newConn.size(),1);
5211   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5212   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5213   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5214   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5215   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5216   std::copy(addCoo.begin(),addCoo.end(),work);
5217   DataArrayDouble::SetArrayIn(newCoords,_coords);
5218   updateTime();
5219 }
5220
5221 /*!
5222  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5223  * In addition, returns an array mapping new cells to old ones. <br>
5224  * This method typically increases the number of cells in \a this mesh
5225  * but the number of nodes remains \b unchanged.
5226  * That's why the 3D splitting policies
5227  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5228  *  \param [in] policy - specifies a pattern used for splitting.
5229  * The semantic of \a policy is:
5230  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5231  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5232  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5233  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5234  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5235  *          an id of old cell producing it. The caller is to delete this array using
5236  *         decrRef() as it is no more needed. 
5237  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5238  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5239  *          and \a this->getMeshDimension() != 3. 
5240  *  \throw If \a policy is not one of the four discussed above.
5241  *  \throw If the nodal connectivity of cells is not defined.
5242  * \sa MEDCouplingUMesh::tetrahedrize
5243  */
5244 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5245 {
5246   switch(policy)
5247     {
5248     case 0:
5249       return simplexizePol0();
5250     case 1:
5251       return simplexizePol1();
5252     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5253       return simplexizePlanarFace5();
5254     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5255       return simplexizePlanarFace6();
5256     default:
5257       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be :\n  - 0 or 1 (only available for meshdim=2) \n  - PLANAR_FACE_5, PLANAR_FACE_6  (only for meshdim=3)");
5258     }
5259 }
5260
5261 /*!
5262  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5263  * - 1D: INTERP_KERNEL::NORM_SEG2
5264  * - 2D: INTERP_KERNEL::NORM_TRI3
5265  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5266  *
5267  * This method is useful for users that need to use P1 field services as
5268  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5269  * All these methods need mesh support containing only simplex cells.
5270  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5271  *  \throw If the coordinates array is not set.
5272  *  \throw If the nodal connectivity of cells is not defined.
5273  *  \throw If \a this->getMeshDimension() < 1.
5274  */
5275 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5276 {
5277   checkFullyDefined();
5278   int mdim=getMeshDimension();
5279   if(mdim<1 || mdim>3)
5280     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5281   int nbCells=getNumberOfCells();
5282   const int *conn=_nodal_connec->getConstPointer();
5283   const int *connI=_nodal_connec_index->getConstPointer();
5284   for(int i=0;i<nbCells;i++)
5285     {
5286       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5287       if(!cm.isSimplex())
5288         return false;
5289     }
5290   return true;
5291 }
5292
5293 /*!
5294  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5295  */
5296 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5297 {
5298   checkConnectivityFullyDefined();
5299   if(getMeshDimension()!=2)
5300     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5301   int nbOfCells=getNumberOfCells();
5302   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5303   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5304   ret->alloc(nbOfCells+nbOfCutCells,1);
5305   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5306   int *retPt=ret->getPointer();
5307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5309   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5310   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5311   int *pt=newConn->getPointer();
5312   int *ptI=newConnI->getPointer();
5313   ptI[0]=0;
5314   const int *oldc=_nodal_connec->getConstPointer();
5315   const int *ci=_nodal_connec_index->getConstPointer();
5316   for(int i=0;i<nbOfCells;i++,ci++)
5317     {
5318       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5319         {
5320           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5321                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5322           pt=std::copy(tmp,tmp+8,pt);
5323           ptI[1]=ptI[0]+4;
5324           ptI[2]=ptI[0]+8;
5325           *retPt++=i;
5326           *retPt++=i;
5327           ptI+=2;
5328         }
5329       else
5330         {
5331           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5332           ptI[1]=ptI[0]+ci[1]-ci[0];
5333           ptI++;
5334           *retPt++=i;
5335         }
5336     }
5337   _nodal_connec->decrRef();
5338   _nodal_connec=newConn.retn();
5339   _nodal_connec_index->decrRef();
5340   _nodal_connec_index=newConnI.retn();
5341   computeTypes();
5342   updateTime();
5343   return ret.retn();
5344 }
5345
5346 /*!
5347  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5348  */
5349 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5350 {
5351   checkConnectivityFullyDefined();
5352   if(getMeshDimension()!=2)
5353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5354   int nbOfCells=getNumberOfCells();
5355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5356   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5357   ret->alloc(nbOfCells+nbOfCutCells,1);
5358   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5359   int *retPt=ret->getPointer();
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5362   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5363   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5364   int *pt=newConn->getPointer();
5365   int *ptI=newConnI->getPointer();
5366   ptI[0]=0;
5367   const int *oldc=_nodal_connec->getConstPointer();
5368   const int *ci=_nodal_connec_index->getConstPointer();
5369   for(int i=0;i<nbOfCells;i++,ci++)
5370     {
5371       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5372         {
5373           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5374                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5375           pt=std::copy(tmp,tmp+8,pt);
5376           ptI[1]=ptI[0]+4;
5377           ptI[2]=ptI[0]+8;
5378           *retPt++=i;
5379           *retPt++=i;
5380           ptI+=2;
5381         }
5382       else
5383         {
5384           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5385           ptI[1]=ptI[0]+ci[1]-ci[0];
5386           ptI++;
5387           *retPt++=i;
5388         }
5389     }
5390   _nodal_connec->decrRef();
5391   _nodal_connec=newConn.retn();
5392   _nodal_connec_index->decrRef();
5393   _nodal_connec_index=newConnI.retn();
5394   computeTypes();
5395   updateTime();
5396   return ret.retn();
5397 }
5398
5399 /*!
5400  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5401  */
5402 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5403 {
5404   checkConnectivityFullyDefined();
5405   if(getMeshDimension()!=3)
5406     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5407   int nbOfCells=getNumberOfCells();
5408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5409   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5410   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5411   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5412   int *retPt=ret->getPointer();
5413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5414   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5415   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5416   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5417   int *pt=newConn->getPointer();
5418   int *ptI=newConnI->getPointer();
5419   ptI[0]=0;
5420   const int *oldc=_nodal_connec->getConstPointer();
5421   const int *ci=_nodal_connec_index->getConstPointer();
5422   for(int i=0;i<nbOfCells;i++,ci++)
5423     {
5424       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5425         {
5426           for(int j=0;j<5;j++,pt+=5,ptI++)
5427             {
5428               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5429               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+3]+1];
5430               *retPt++=i;
5431               ptI[1]=ptI[0]+5;
5432             }
5433         }
5434       else
5435         {
5436           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5437           ptI[1]=ptI[0]+ci[1]-ci[0];
5438           ptI++;
5439           *retPt++=i;
5440         }
5441     }
5442   _nodal_connec->decrRef();
5443   _nodal_connec=newConn.retn();
5444   _nodal_connec_index->decrRef();
5445   _nodal_connec_index=newConnI.retn();
5446   computeTypes();
5447   updateTime();
5448   return ret.retn();
5449 }
5450
5451 /*!
5452  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5453  */
5454 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5455 {
5456   checkConnectivityFullyDefined();
5457   if(getMeshDimension()!=3)
5458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5459   int nbOfCells=getNumberOfCells();
5460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5461   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5462   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5463   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5464   int *retPt=ret->getPointer();
5465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5467   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5468   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5469   int *pt=newConn->getPointer();
5470   int *ptI=newConnI->getPointer();
5471   ptI[0]=0;
5472   const int *oldc=_nodal_connec->getConstPointer();
5473   const int *ci=_nodal_connec_index->getConstPointer();
5474   for(int i=0;i<nbOfCells;i++,ci++)
5475     {
5476       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5477         {
5478           for(int j=0;j<6;j++,pt+=5,ptI++)
5479             {
5480               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5481               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+3]+1];
5482               *retPt++=i;
5483               ptI[1]=ptI[0]+5;
5484             }
5485         }
5486       else
5487         {
5488           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5489           ptI[1]=ptI[0]+ci[1]-ci[0];
5490           ptI++;
5491           *retPt++=i;
5492         }
5493     }
5494   _nodal_connec->decrRef();
5495   _nodal_connec=newConn.retn();
5496   _nodal_connec_index->decrRef();
5497   _nodal_connec_index=newConnI.retn();
5498   computeTypes();
5499   updateTime();
5500   return ret.retn();
5501 }
5502
5503 /*!
5504  * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5505  * This method completly ignore coordinates.
5506  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5507  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5508  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5509  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5510  */
5511 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5512 {
5513   checkFullyDefined();
5514   if(getMeshDimension()!=2)
5515     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5516   int nbOfCells=getNumberOfCells();
5517   int *connI=_nodal_connec_index->getPointer();
5518   int newConnLgth=0;
5519   for(int i=0;i<nbOfCells;i++,connI++)
5520     {
5521       int offset=descIndex[i];
5522       int nbOfEdges=descIndex[i+1]-offset;
5523       //
5524       bool ddirect=desc[offset+nbOfEdges-1]>0;
5525       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5526       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5527       for(int j=0;j<nbOfEdges;j++)
5528         {
5529           bool direct=desc[offset+j]>0;
5530           int edgeId=std::abs(desc[offset+j])-1;
5531           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5532             {
5533               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5534               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5535               int ref2=direct?id1:id2;
5536               if(ref==ref2)
5537                 {
5538                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5539                   newConnLgth+=nbOfSubNodes-1;
5540                   ref=direct?id2:id1;
5541                 }
5542               else
5543                 {
5544                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5545                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5546                 }
5547             }
5548           else
5549             {
5550               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5551             }
5552         }
5553       newConnLgth++;//+1 is for cell type
5554       connI[1]=newConnLgth;
5555     }
5556   //
5557   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5558   newConn->alloc(newConnLgth,1);
5559   int *work=newConn->getPointer();
5560   for(int i=0;i<nbOfCells;i++)
5561     {
5562       *work++=INTERP_KERNEL::NORM_POLYGON;
5563       int offset=descIndex[i];
5564       int nbOfEdges=descIndex[i+1]-offset;
5565       for(int j=0;j<nbOfEdges;j++)
5566         {
5567           bool direct=desc[offset+j]>0;
5568           int edgeId=std::abs(desc[offset+j])-1;
5569           if(direct)
5570             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5571           else
5572             {
5573               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5574               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5575               work=std::copy(it,it+nbOfSubNodes-1,work);
5576             }
5577         }
5578     }
5579   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5580   _types.clear();
5581   if(nbOfCells>0)
5582     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5583 }
5584
5585 /*!
5586  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5587  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5588  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5589  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5590  * so it can be useful to call mergeNodes() before calling this method.
5591  *  \throw If \a this->getMeshDimension() <= 1.
5592  *  \throw If the coordinates array is not set.
5593  *  \throw If the nodal connectivity of cells is not defined.
5594  */
5595 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5596 {
5597   checkFullyDefined();
5598   if(getMeshDimension()<=1)
5599     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5600   int nbOfCells=getNumberOfCells();
5601   if(nbOfCells<1)
5602     return ;
5603   int initMeshLgth=getMeshLength();
5604   int *conn=_nodal_connec->getPointer();
5605   int *index=_nodal_connec_index->getPointer();
5606   int posOfCurCell=0;
5607   int newPos=0;
5608   int lgthOfCurCell;
5609   for(int i=0;i<nbOfCells;i++)
5610     {
5611       lgthOfCurCell=index[i+1]-posOfCurCell;
5612       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5613       int newLgth;
5614       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5615                                                                                                      conn+newPos+1,newLgth);
5616       conn[newPos]=newType;
5617       newPos+=newLgth+1;
5618       posOfCurCell=index[i+1];
5619       index[i+1]=newPos;
5620     }
5621   if(newPos!=initMeshLgth)
5622     _nodal_connec->reAlloc(newPos);
5623   computeTypes();
5624 }
5625
5626 /*!
5627  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5628  * A cell is considered to be oriented correctly if an angle between its
5629  * normal vector and a given vector is less than \c PI / \c 2.
5630  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5631  *         cells. 
5632  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5633  *         checked.
5634  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5635  *         is not cleared before filling in.
5636  *  \throw If \a this->getMeshDimension() != 2.
5637  *  \throw If \a this->getSpaceDimension() != 3.
5638  *
5639  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5640  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5641  */
5642 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5643 {
5644   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5645     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5646   int nbOfCells=getNumberOfCells();
5647   const int *conn=_nodal_connec->getConstPointer();
5648   const int *connI=_nodal_connec_index->getConstPointer();
5649   const double *coordsPtr=_coords->getConstPointer();
5650   for(int i=0;i<nbOfCells;i++)
5651     {
5652       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5653       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5654         {
5655           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5656           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5657             cells.push_back(i);
5658         }
5659     }
5660 }
5661
5662 /*!
5663  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5664  * considered to be oriented correctly if an angle between its normal vector and a
5665  * given vector is less than \c PI / \c 2. 
5666  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5667  *         cells. 
5668  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5669  *         checked.
5670  *  \throw If \a this->getMeshDimension() != 2.
5671  *  \throw If \a this->getSpaceDimension() != 3.
5672  *
5673  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5674  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5675  */
5676 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5677 {
5678   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5679     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5680   int nbOfCells=getNumberOfCells();
5681   int *conn=_nodal_connec->getPointer();
5682   const int *connI=_nodal_connec_index->getConstPointer();
5683   const double *coordsPtr=_coords->getConstPointer();
5684   bool isModified=false;
5685   for(int i=0;i<nbOfCells;i++)
5686     {
5687       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5688       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5689         {
5690           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5691           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5692             {
5693               isModified=true;
5694               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5695               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5696               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5697             }
5698         }
5699     }
5700   if(isModified)
5701     _nodal_connec->declareAsNew();
5702   updateTime();
5703 }
5704
5705 /*!
5706  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5707  * oriented facets. The normal vector of the facet should point out of the cell.
5708  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5709  *         is not cleared before filling in.
5710  *  \throw If \a this->getMeshDimension() != 3.
5711  *  \throw If \a this->getSpaceDimension() != 3.
5712  *  \throw If the coordinates array is not set.
5713  *  \throw If the nodal connectivity of cells is not defined.
5714  *
5715  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5716  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5717  */
5718 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5719 {
5720   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5721     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5722   int nbOfCells=getNumberOfCells();
5723   const int *conn=_nodal_connec->getConstPointer();
5724   const int *connI=_nodal_connec_index->getConstPointer();
5725   const double *coordsPtr=_coords->getConstPointer();
5726   for(int i=0;i<nbOfCells;i++)
5727     {
5728       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5729       if(type==INTERP_KERNEL::NORM_POLYHED)
5730         {
5731           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5732             cells.push_back(i);
5733         }
5734     }
5735 }
5736
5737 /*!
5738  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5739  * out of the cell. 
5740  *  \throw If \a this->getMeshDimension() != 3.
5741  *  \throw If \a this->getSpaceDimension() != 3.
5742  *  \throw If the coordinates array is not set.
5743  *  \throw If the nodal connectivity of cells is not defined.
5744  *  \throw If the reparation fails.
5745  *
5746  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5747  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5748  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5749  */
5750 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5751 {
5752   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5753     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5754   int nbOfCells=getNumberOfCells();
5755   int *conn=_nodal_connec->getPointer();
5756   const int *connI=_nodal_connec_index->getConstPointer();
5757   const double *coordsPtr=_coords->getConstPointer();
5758   for(int i=0;i<nbOfCells;i++)
5759     {
5760       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5761       if(type==INTERP_KERNEL::NORM_POLYHED)
5762         {
5763           try
5764             {
5765               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5766                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5767             }
5768           catch(INTERP_KERNEL::Exception& e)
5769             {
5770               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5771               throw INTERP_KERNEL::Exception(oss.str().c_str());
5772             }
5773         }
5774     }
5775   updateTime();
5776 }
5777
5778 /*!
5779  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5780  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5781  * according to which the first facet of the cell should be oriented to have the normal vector
5782  * pointing out of cell.
5783  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5784  *         cells. The caller is to delete this array using decrRef() as it is no more
5785  *         needed. 
5786  *  \throw If \a this->getMeshDimension() != 3.
5787  *  \throw If \a this->getSpaceDimension() != 3.
5788  *  \throw If the coordinates array is not set.
5789  *  \throw If the nodal connectivity of cells is not defined.
5790  *
5791  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5792  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5793  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5794  */
5795 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5796 {
5797   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5798   if(getMeshDimension()!=3)
5799     throw INTERP_KERNEL::Exception(msg);
5800   int spaceDim=getSpaceDimension();
5801   if(spaceDim!=3)
5802     throw INTERP_KERNEL::Exception(msg);
5803   //
5804   int nbOfCells=getNumberOfCells();
5805   int *conn=_nodal_connec->getPointer();
5806   const int *connI=_nodal_connec_index->getConstPointer();
5807   const double *coo=getCoords()->getConstPointer();
5808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5809   for(int i=0;i<nbOfCells;i++)
5810     {
5811       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5812       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5813         {
5814           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5815             {
5816               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5817               cells->pushBackSilent(i);
5818             }
5819         }
5820     }
5821   return cells.retn();
5822 }
5823
5824 /*!
5825  * This method is a faster method to correct orientation of all 3D cells in \a this.
5826  * This method works only if \a this is a 3D mesh, that is to say a mesh with mesh dimension 3 and a space dimension 3.
5827  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5828  * 
5829  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5830  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5831  */
5832 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5833 {
5834   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5835     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5836   int nbOfCells=getNumberOfCells();
5837   int *conn=_nodal_connec->getPointer();
5838   const int *connI=_nodal_connec_index->getConstPointer();
5839   const double *coordsPtr=_coords->getConstPointer();
5840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5841   for(int i=0;i<nbOfCells;i++)
5842     {
5843       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5844       switch(type)
5845         {
5846         case INTERP_KERNEL::NORM_TETRA4:
5847           {
5848             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5849               {
5850                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5851                 ret->pushBackSilent(i);
5852               }
5853             break;
5854           }
5855         case INTERP_KERNEL::NORM_PYRA5:
5856           {
5857             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5858               {
5859                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5860                 ret->pushBackSilent(i);
5861               }
5862             break;
5863           }
5864         case INTERP_KERNEL::NORM_PENTA6:
5865         case INTERP_KERNEL::NORM_HEXA8:
5866         case INTERP_KERNEL::NORM_HEXGP12:
5867           {
5868             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5869               {
5870                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5871                 ret->pushBackSilent(i);
5872               }
5873             break;
5874           }
5875         case INTERP_KERNEL::NORM_POLYHED:
5876           {
5877             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5878               {
5879                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5880                 ret->pushBackSilent(i);
5881               }
5882             break;
5883           }
5884         default:
5885           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orientCorrectly3DCells : Your mesh contains type of cell not supported yet ! send mail to anthony.geay@cea.fr to add it !");
5886         }
5887     }
5888   updateTime();
5889   return ret.retn();
5890 }
5891
5892 /*!
5893  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5894  * If it is not the case an exception will be thrown.
5895  * This method is fast because the first cell of \a this is used to compute the plane.
5896  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5897  * \param pos output of size at least 3 used to store a point owned of searched plane.
5898  */
5899 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5900 {
5901   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5902     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5903   const int *conn=_nodal_connec->getConstPointer();
5904   const int *connI=_nodal_connec_index->getConstPointer();
5905   const double *coordsPtr=_coords->getConstPointer();
5906   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5907   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5908 }
5909
5910 /*!
5911  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5912  * cells. Currently cells of the following types are treated:
5913  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5914  * For a cell of other type an exception is thrown.
5915  * Space dimension of a 2D mesh can be either 2 or 3.
5916  * The Edge Ratio of a cell \f$t\f$ is: 
5917  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5918  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5919  *  the smallest edge lengths of \f$t\f$.
5920  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5921  *          cells and one time, lying on \a this mesh. The caller is to delete this
5922  *          field using decrRef() as it is no more needed. 
5923  *  \throw If the coordinates array is not set.
5924  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5925  *  \throw If the connectivity data array has more than one component.
5926  *  \throw If the connectivity data array has a named component.
5927  *  \throw If the connectivity index data array has more than one component.
5928  *  \throw If the connectivity index data array has a named component.
5929  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5930  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5931  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5932  */
5933 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5934 {
5935   checkCoherency();
5936   int spaceDim=getSpaceDimension();
5937   int meshDim=getMeshDimension();
5938   if(spaceDim!=2 && spaceDim!=3)
5939     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5940   if(meshDim!=2 && meshDim!=3)
5941     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5942   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5943   ret->setMesh(this);
5944   int nbOfCells=getNumberOfCells();
5945   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5946   arr->alloc(nbOfCells,1);
5947   double *pt=arr->getPointer();
5948   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5949   const int *conn=_nodal_connec->getConstPointer();
5950   const int *connI=_nodal_connec_index->getConstPointer();
5951   const double *coo=_coords->getConstPointer();
5952   double tmp[12];
5953   for(int i=0;i<nbOfCells;i++,pt++)
5954     {
5955       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5956       switch(t)
5957         {
5958           case INTERP_KERNEL::NORM_TRI3:
5959             {
5960               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5961               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5962               break;
5963             }
5964           case INTERP_KERNEL::NORM_QUAD4:
5965             {
5966               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5967               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5968               break;
5969             }
5970           case INTERP_KERNEL::NORM_TETRA4:
5971             {
5972               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5973               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5974               break;
5975             }
5976         default:
5977           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5978         }
5979       conn+=connI[i+1]-connI[i];
5980     }
5981   ret->setName("EdgeRatio");
5982   ret->synchronizeTimeWithSupport();
5983   return ret.retn();
5984 }
5985
5986 /*!
5987  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5988  * cells. Currently cells of the following types are treated:
5989  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5990  * For a cell of other type an exception is thrown.
5991  * Space dimension of a 2D mesh can be either 2 or 3.
5992  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5993  *          cells and one time, lying on \a this mesh. The caller is to delete this
5994  *          field using decrRef() as it is no more needed. 
5995  *  \throw If the coordinates array is not set.
5996  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5997  *  \throw If the connectivity data array has more than one component.
5998  *  \throw If the connectivity data array has a named component.
5999  *  \throw If the connectivity index data array has more than one component.
6000  *  \throw If the connectivity index data array has a named component.
6001  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6002  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6003  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6004  */
6005 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6006 {
6007   checkCoherency();
6008   int spaceDim=getSpaceDimension();
6009   int meshDim=getMeshDimension();
6010   if(spaceDim!=2 && spaceDim!=3)
6011     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6012   if(meshDim!=2 && meshDim!=3)
6013     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6014   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6015   ret->setMesh(this);
6016   int nbOfCells=getNumberOfCells();
6017   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6018   arr->alloc(nbOfCells,1);
6019   double *pt=arr->getPointer();
6020   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6021   const int *conn=_nodal_connec->getConstPointer();
6022   const int *connI=_nodal_connec_index->getConstPointer();
6023   const double *coo=_coords->getConstPointer();
6024   double tmp[12];
6025   for(int i=0;i<nbOfCells;i++,pt++)
6026     {
6027       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6028       switch(t)
6029         {
6030           case INTERP_KERNEL::NORM_TRI3:
6031             {
6032               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6033               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6034               break;
6035             }
6036           case INTERP_KERNEL::NORM_QUAD4:
6037             {
6038               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6039               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6040               break;
6041             }
6042           case INTERP_KERNEL::NORM_TETRA4:
6043             {
6044               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6045               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6046               break;
6047             }
6048         default:
6049           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6050         }
6051       conn+=connI[i+1]-connI[i];
6052     }
6053   ret->setName("AspectRatio");
6054   ret->synchronizeTimeWithSupport();
6055   return ret.retn();
6056 }
6057
6058 /*!
6059  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6060  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6061  * treated: INTERP_KERNEL::NORM_QUAD4.
6062  * For a cell of other type an exception is thrown.
6063  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6064  *          cells and one time, lying on \a this mesh. The caller is to delete this
6065  *          field using decrRef() as it is no more needed. 
6066  *  \throw If the coordinates array is not set.
6067  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6068  *  \throw If the connectivity data array has more than one component.
6069  *  \throw If the connectivity data array has a named component.
6070  *  \throw If the connectivity index data array has more than one component.
6071  *  \throw If the connectivity index data array has a named component.
6072  *  \throw If \a this->getMeshDimension() != 2.
6073  *  \throw If \a this->getSpaceDimension() != 3.
6074  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6075  */
6076 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6077 {
6078   checkCoherency();
6079   int spaceDim=getSpaceDimension();
6080   int meshDim=getMeshDimension();
6081   if(spaceDim!=3)
6082     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6083   if(meshDim!=2)
6084     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6085   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6086   ret->setMesh(this);
6087   int nbOfCells=getNumberOfCells();
6088   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6089   arr->alloc(nbOfCells,1);
6090   double *pt=arr->getPointer();
6091   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6092   const int *conn=_nodal_connec->getConstPointer();
6093   const int *connI=_nodal_connec_index->getConstPointer();
6094   const double *coo=_coords->getConstPointer();
6095   double tmp[12];
6096   for(int i=0;i<nbOfCells;i++,pt++)
6097     {
6098       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6099       switch(t)
6100         {
6101           case INTERP_KERNEL::NORM_QUAD4:
6102             {
6103               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6104               *pt=INTERP_KERNEL::quadWarp(tmp);
6105               break;
6106             }
6107         default:
6108           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6109         }
6110       conn+=connI[i+1]-connI[i];
6111     }
6112   ret->setName("Warp");
6113   ret->synchronizeTimeWithSupport();
6114   return ret.retn();
6115 }
6116
6117
6118 /*!
6119  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6120  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6121  * treated: INTERP_KERNEL::NORM_QUAD4.
6122  * For a cell of other type an exception is thrown.
6123  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6124  *          cells and one time, lying on \a this mesh. The caller is to delete this
6125  *          field using decrRef() as it is no more needed. 
6126  *  \throw If the coordinates array is not set.
6127  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6128  *  \throw If the connectivity data array has more than one component.
6129  *  \throw If the connectivity data array has a named component.
6130  *  \throw If the connectivity index data array has more than one component.
6131  *  \throw If the connectivity index data array has a named component.
6132  *  \throw If \a this->getMeshDimension() != 2.
6133  *  \throw If \a this->getSpaceDimension() != 3.
6134  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6135  */
6136 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6137 {
6138   checkCoherency();
6139   int spaceDim=getSpaceDimension();
6140   int meshDim=getMeshDimension();
6141   if(spaceDim!=3)
6142     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6143   if(meshDim!=2)
6144     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6145   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6146   ret->setMesh(this);
6147   int nbOfCells=getNumberOfCells();
6148   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6149   arr->alloc(nbOfCells,1);
6150   double *pt=arr->getPointer();
6151   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6152   const int *conn=_nodal_connec->getConstPointer();
6153   const int *connI=_nodal_connec_index->getConstPointer();
6154   const double *coo=_coords->getConstPointer();
6155   double tmp[12];
6156   for(int i=0;i<nbOfCells;i++,pt++)
6157     {
6158       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6159       switch(t)
6160         {
6161           case INTERP_KERNEL::NORM_QUAD4:
6162             {
6163               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6164               *pt=INTERP_KERNEL::quadSkew(tmp);
6165               break;
6166             }
6167         default:
6168           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6169         }
6170       conn+=connI[i+1]-connI[i];
6171     }
6172   ret->setName("Skew");
6173   ret->synchronizeTimeWithSupport();
6174   return ret.retn();
6175 }
6176
6177 /*!
6178  * This method aggregate the bbox of each cell and put it into bbox parameter.
6179  * 
6180  * \return DataArrayDouble * - having \a this number of cells tuples and 2*spacedim components.
6181  * 
6182  * \throw If \a this is not fully set (coordinates and connectivity).
6183  * \throw If a cell in \a this has no valid nodeId.
6184  */
6185 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree() const
6186 {
6187   checkFullyDefined();
6188   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6189   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6190   double *bbox(ret->getPointer());
6191   for(int i=0;i<nbOfCells*spaceDim;i++)
6192     {
6193       bbox[2*i]=std::numeric_limits<double>::max();
6194       bbox[2*i+1]=-std::numeric_limits<double>::max();
6195     }
6196   const double *coordsPtr(_coords->getConstPointer());
6197   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6198   for(int i=0;i<nbOfCells;i++)
6199     {
6200       int offset=connI[i]+1;
6201       int nbOfNodesForCell=connI[i+1]-offset;
6202       for(int j=0;j<nbOfNodesForCell;j++)
6203         {
6204           int nodeId=conn[offset+j];
6205           int kk(0);
6206           if(nodeId>=0 && nodeId<nbOfNodes)
6207             {
6208               for(int k=0;k<spaceDim;k++)
6209                 {
6210                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6211                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6212                 }
6213               kk++;
6214             }
6215           if(kk==0)
6216             {
6217               std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6218               throw INTERP_KERNEL::Exception(oss.str().c_str());
6219             }
6220         }
6221     }
6222   return ret.retn();
6223 }
6224
6225 /// @cond INTERNAL
6226
6227 namespace ParaMEDMEMImpl
6228 {
6229   class ConnReader
6230   {
6231   public:
6232     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6233     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6234   private:
6235     const int *_conn;
6236     int _val;
6237   };
6238
6239   class ConnReader2
6240   {
6241   public:
6242     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6243     bool operator() (const int& pos) { return _conn[pos]==_val; }
6244   private:
6245     const int *_conn;
6246     int _val;
6247   };
6248 }
6249
6250 /// @endcond
6251
6252 /*!
6253  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6254  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6255  * \a this is composed in cell types.
6256  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6257  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6258  * This parameter is kept only for compatibility with other methode listed above.
6259  */
6260 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6261 {
6262   checkConnectivityFullyDefined();
6263   const int *conn=_nodal_connec->getConstPointer();
6264   const int *connI=_nodal_connec_index->getConstPointer();
6265   const int *work=connI;
6266   int nbOfCells=getNumberOfCells();
6267   std::size_t n=getAllTypes().size();
6268   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6269   std::set<INTERP_KERNEL::NormalizedCellType> types;
6270   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6271     {
6272       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6273       if(types.find(typ)!=types.end())
6274         {
6275           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6276           oss << " is not contiguous !";
6277           throw INTERP_KERNEL::Exception(oss.str().c_str());
6278         }
6279       types.insert(typ);
6280       ret[3*i]=typ;
6281       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6282       ret[3*i+1]=(int)std::distance(work,work2);
6283       work=work2;
6284     }
6285   return ret;
6286 }
6287
6288 /*!
6289  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6290  * only for types cell, type node is not managed.
6291  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6292  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6293  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6294  * If 2 or more same geometric type is in \a code and exception is thrown too.
6295  *
6296  * This method firstly checks
6297  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6298  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6299  * an exception is thrown too.
6300  * 
6301  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6302  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6303  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6304  */
6305 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6306 {
6307   if(code.empty())
6308     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6309   std::size_t sz=code.size();
6310   std::size_t n=sz/3;
6311   if(sz%3!=0)
6312     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6313   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6314   int nb=0;
6315   bool isNoPflUsed=true;
6316   for(std::size_t i=0;i<n;i++)
6317     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6318       {
6319         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6320         nb+=code[3*i+1];
6321         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6322           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6323         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6324       }
6325   if(types.size()!=n)
6326     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6327   if(isNoPflUsed)
6328     {
6329       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6330         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6331       if(types.size()==_types.size())
6332         return 0;
6333     }
6334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6335   ret->alloc(nb,1);
6336   int *retPtr=ret->getPointer();
6337   const int *connI=_nodal_connec_index->getConstPointer();
6338   const int *conn=_nodal_connec->getConstPointer();
6339   int nbOfCells=getNumberOfCells();
6340   const int *i=connI;
6341   int kk=0;
6342   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6343     {
6344       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6345       int offset=(int)std::distance(connI,i);
6346       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6347       int nbOfCellsOfCurType=(int)std::distance(i,j);
6348       if(code[3*kk+2]==-1)
6349         for(int k=0;k<nbOfCellsOfCurType;k++)
6350           *retPtr++=k+offset;
6351       else
6352         {
6353           int idInIdsPerType=code[3*kk+2];
6354           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6355             {
6356               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6357               if(zePfl)
6358                 {
6359                   zePfl->checkAllocated();
6360                   if(zePfl->getNumberOfComponents()==1)
6361                     {
6362                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6363                         {
6364                           if(*k>=0 && *k<nbOfCellsOfCurType)
6365                             *retPtr=(*k)+offset;
6366                           else
6367                             {
6368                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6369                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6370                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6371                             }
6372                         }
6373                     }
6374                   else
6375                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6376                 }
6377               else
6378                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6379             }
6380           else
6381             {
6382               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6383               oss << " should be in [0," << idsPerType.size() << ") !";
6384               throw INTERP_KERNEL::Exception(oss.str().c_str());
6385             }
6386         }
6387       i=j;
6388     }
6389   return ret.retn();
6390 }
6391
6392 /*!
6393  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6394  * 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.
6395  * 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.
6396  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6397  * 
6398  * \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.
6399  * \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,
6400  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6401  * \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.
6402  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6403  * \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
6404  */
6405 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6406 {
6407   if(!profile)
6408     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6409   if(profile->getNumberOfComponents()!=1)
6410     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6411   checkConnectivityFullyDefined();
6412   const int *conn=_nodal_connec->getConstPointer();
6413   const int *connI=_nodal_connec_index->getConstPointer();
6414   int nbOfCells=getNumberOfCells();
6415   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6416   std::vector<int> typeRangeVals(1);
6417   for(const int *i=connI;i!=connI+nbOfCells;)
6418     {
6419       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6420       if(std::find(types.begin(),types.end(),curType)!=types.end())
6421         {
6422           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6423         }
6424       types.push_back(curType);
6425       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6426       typeRangeVals.push_back((int)std::distance(connI,i));
6427     }
6428   //
6429   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6430   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6433   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6434   //
6435   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6436   code.resize(3*nbOfCastsFinal);
6437   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6438   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6439   for(int i=0;i<nbOfCastsFinal;i++)
6440     {
6441       int castId=castsPresent->getIJ(i,0);
6442       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6443       idsInPflPerType2.push_back(tmp3);
6444       code[3*i]=(int)types[castId];
6445       code[3*i+1]=tmp3->getNumberOfTuples();
6446       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6447       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6448         {
6449           tmp4->copyStringInfoFrom(*profile);
6450           idsPerType2.push_back(tmp4);
6451           code[3*i+2]=(int)idsPerType2.size()-1;
6452         }
6453       else
6454         {
6455           code[3*i+2]=-1;
6456         }
6457     }
6458   std::size_t sz2=idsInPflPerType2.size();
6459   idsInPflPerType.resize(sz2);
6460   for(std::size_t i=0;i<sz2;i++)
6461     {
6462       DataArrayInt *locDa=idsInPflPerType2[i];
6463       locDa->incrRef();
6464       idsInPflPerType[i]=locDa;
6465     }
6466   std::size_t sz=idsPerType2.size();
6467   idsPerType.resize(sz);
6468   for(std::size_t i=0;i<sz;i++)
6469     {
6470       DataArrayInt *locDa=idsPerType2[i];
6471       locDa->incrRef();
6472       idsPerType[i]=locDa;
6473     }
6474 }
6475
6476 /*!
6477  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6478  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6479  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6480  * 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.
6481  */
6482 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6483 {
6484   checkFullyDefined();
6485   nM1LevMesh->checkFullyDefined();
6486   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6487     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6488   if(_coords!=nM1LevMesh->getCoords())
6489     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6491   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6492   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6493   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6494   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6495   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6496   tmp->setConnectivity(tmp0,tmp1);
6497   tmp->renumberCells(ret0->getConstPointer(),false);
6498   revDesc=tmp->getNodalConnectivity();
6499   revDescIndx=tmp->getNodalConnectivityIndex();
6500   DataArrayInt *ret=0;
6501   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6502     {
6503       int tmp2;
6504       ret->getMaxValue(tmp2);
6505       ret->decrRef();
6506       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6507       throw INTERP_KERNEL::Exception(oss.str().c_str());
6508     }
6509   nM1LevMeshIds=ret;
6510   //
6511   revDesc->incrRef();
6512   revDescIndx->incrRef();
6513   ret1->incrRef();
6514   ret0->incrRef();
6515   meshnM1Old2New=ret0;
6516   return ret1;
6517 }
6518
6519 /*!
6520  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6521  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6522  * in "Old to New" mode.
6523  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6524  *          this array using decrRef() as it is no more needed.
6525  *  \throw If the nodal connectivity of cells is not defined.
6526  */
6527 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6528 {
6529   checkConnectivityFullyDefined();
6530   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6531   renumberCells(ret->getConstPointer(),false);
6532   return ret.retn();
6533 }
6534
6535 /*!
6536  * This methods checks that cells are sorted by their types.
6537  * This method makes asumption (no check) that connectivity is correctly set before calling.
6538  */
6539 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6540 {
6541   checkFullyDefined();
6542   const int *conn=_nodal_connec->getConstPointer();
6543   const int *connI=_nodal_connec_index->getConstPointer();
6544   int nbOfCells=getNumberOfCells();
6545   std::set<INTERP_KERNEL::NormalizedCellType> types;
6546   for(const int *i=connI;i!=connI+nbOfCells;)
6547     {
6548       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6549       if(types.find(curType)!=types.end())
6550         return false;
6551       types.insert(curType);
6552       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6553     }
6554   return true;
6555 }
6556
6557 /*!
6558  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6559  * The geometric type order is specified by MED file.
6560  * 
6561  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6562  */
6563 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6564 {
6565   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6566 }
6567
6568 /*!
6569  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6570  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6571  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6572  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6573  */
6574 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6575 {
6576   checkFullyDefined();
6577   const int *conn=_nodal_connec->getConstPointer();
6578   const int *connI=_nodal_connec_index->getConstPointer();
6579   int nbOfCells=getNumberOfCells();
6580   if(nbOfCells==0)
6581     return true;
6582   int lastPos=-1;
6583   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6584   for(const int *i=connI;i!=connI+nbOfCells;)
6585     {
6586       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6587       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6588       if(isTypeExists!=orderEnd)
6589         {
6590           int pos=(int)std::distance(orderBg,isTypeExists);
6591           if(pos<=lastPos)
6592             return false;
6593           lastPos=pos;
6594           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6595         }
6596       else
6597         {
6598           if(sg.find(curType)==sg.end())
6599             {
6600               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6601               sg.insert(curType);
6602             }
6603           else
6604             return false;
6605         }
6606     }
6607   return true;
6608 }
6609
6610 /*!
6611  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6612  * 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
6613  * 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'.
6614  */
6615 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6616 {
6617   checkConnectivityFullyDefined();
6618   int nbOfCells=getNumberOfCells();
6619   const int *conn=_nodal_connec->getConstPointer();
6620   const int *connI=_nodal_connec_index->getConstPointer();
6621   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6622   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6623   tmpa->alloc(nbOfCells,1);
6624   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6625   tmpb->fillWithZero();
6626   int *tmp=tmpa->getPointer();
6627   int *tmp2=tmpb->getPointer();
6628   for(const int *i=connI;i!=connI+nbOfCells;i++)
6629     {
6630       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6631       if(where!=orderEnd)
6632         {
6633           int pos=(int)std::distance(orderBg,where);
6634           tmp2[pos]++;
6635           tmp[std::distance(connI,i)]=pos;
6636         }
6637       else
6638         {
6639           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6640           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6641           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6642           throw INTERP_KERNEL::Exception(oss.str().c_str());
6643         }
6644     }
6645   nbPerType=tmpb.retn();
6646   return tmpa.retn();
6647 }
6648
6649 /*!
6650  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6651  *
6652  * \return a new object containing the old to new correspondance.
6653  *
6654  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6655  */
6656 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6657 {
6658   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6659 }
6660
6661 /*!
6662  * 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.
6663  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6664  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6665  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6666  */
6667 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6668 {
6669   DataArrayInt *nbPerType=0;
6670   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6671   nbPerType->decrRef();
6672   return tmpa->buildPermArrPerLevel();
6673 }
6674
6675 /*!
6676  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6677  * The number of cells remains unchanged after the call of this method.
6678  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6679  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6680  *
6681  * \return the array giving the correspondance old to new.
6682  */
6683 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6684 {
6685   checkFullyDefined();
6686   computeTypes();
6687   const int *conn=_nodal_connec->getConstPointer();
6688   const int *connI=_nodal_connec_index->getConstPointer();
6689   int nbOfCells=getNumberOfCells();
6690   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6691   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6692     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6693       {
6694         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6695         types.push_back(curType);
6696         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6697       }
6698   DataArrayInt *ret=DataArrayInt::New();
6699   ret->alloc(nbOfCells,1);
6700   int *retPtr=ret->getPointer();
6701   std::fill(retPtr,retPtr+nbOfCells,-1);
6702   int newCellId=0;
6703   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6704     {
6705       for(const int *i=connI;i!=connI+nbOfCells;i++)
6706         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6707           retPtr[std::distance(connI,i)]=newCellId++;
6708     }
6709   renumberCells(retPtr,false);
6710   return ret;
6711 }
6712
6713 /*!
6714  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6715  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6716  * This method makes asumption that connectivity is correctly set before calling.
6717  */
6718 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6719 {
6720   checkConnectivityFullyDefined();
6721   const int *conn=_nodal_connec->getConstPointer();
6722   const int *connI=_nodal_connec_index->getConstPointer();
6723   int nbOfCells=getNumberOfCells();
6724   std::vector<MEDCouplingUMesh *> ret;
6725   for(const int *i=connI;i!=connI+nbOfCells;)
6726     {
6727       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6728       int beginCellId=(int)std::distance(connI,i);
6729       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6730       int endCellId=(int)std::distance(connI,i);
6731       int sz=endCellId-beginCellId;
6732       int *cells=new int[sz];
6733       for(int j=0;j<sz;j++)
6734         cells[j]=beginCellId+j;
6735       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6736       delete [] cells;
6737       ret.push_back(m);
6738     }
6739   return ret;
6740 }
6741
6742 /*!
6743  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6744  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6745  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6746  *
6747  * \return a newly allocated instance, that the caller must manage.
6748  * \throw If \a this contains more than one geometric type.
6749  * \throw If the nodal connectivity of \a this is not fully defined.
6750  * \throw If the internal data is not coherent.
6751  */
6752 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6753 {
6754   checkConnectivityFullyDefined();
6755     if(_types.size()!=1)
6756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6757   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6758   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6759   ret->setCoords(getCoords());
6760   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6761   if(retC)
6762     {
6763       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6764       retC->setNodalConnectivity(c);
6765     }
6766   else
6767     {
6768       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6769       if(!retD)
6770         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6771       DataArrayInt *c=0,*ci=0;
6772       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6773       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6774       retD->setNodalConnectivity(cs,cis);
6775     }
6776   return ret.retn();
6777 }
6778
6779 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6780 {
6781   checkConnectivityFullyDefined();
6782     if(_types.size()!=1)
6783     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6784   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6785   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6786   if(cm.isDynamic())
6787     {
6788       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6789       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6790       throw INTERP_KERNEL::Exception(oss.str().c_str());
6791     }
6792   int nbCells=getNumberOfCells();
6793   int typi=(int)typ;
6794   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6795   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6796   int *outPtr=connOut->getPointer();
6797   const int *conn=_nodal_connec->begin();
6798   const int *connI=_nodal_connec_index->begin();
6799   nbNodesPerCell++;
6800   for(int i=0;i<nbCells;i++,connI++)
6801     {
6802       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6803         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6804       else
6805         {
6806           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 << ") !";
6807           throw INTERP_KERNEL::Exception(oss.str().c_str());
6808         }
6809     }
6810   return connOut.retn();
6811 }
6812
6813 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6814 {
6815   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6816   checkConnectivityFullyDefined();
6817   if(_types.size()!=1)
6818     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6819   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6820   if(lgth<nbCells)
6821     throw INTERP_KERNEL::Exception(msg0);
6822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6823   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6824   int *cp(c->getPointer()),*cip(ci->getPointer());
6825   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6826   cip[0]=0;
6827   for(int i=0;i<nbCells;i++,cip++,incip++)
6828     {
6829       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6830       int delta(stop-strt);
6831       if(delta>=1)
6832         {
6833           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6834             cp=std::copy(incp+strt,incp+stop,cp);
6835           else
6836             throw INTERP_KERNEL::Exception(msg0);
6837         }
6838       else
6839         throw INTERP_KERNEL::Exception(msg0);
6840       cip[1]=cip[0]+delta;
6841     }
6842   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6843 }
6844
6845 /*!
6846  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6847  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6848  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6849  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6850  * are not used here to avoid the build of big permutation array.
6851  *
6852  * \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
6853  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6854  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6855  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6856  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6857  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6858  * \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
6859  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6860  */
6861 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6862                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6863                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6864 {
6865   std::vector<const MEDCouplingUMesh *> ms2;
6866   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6867     if(*it)
6868       {
6869         (*it)->checkConnectivityFullyDefined();
6870         ms2.push_back(*it);
6871       }
6872   if(ms2.empty())
6873     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6874   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6875   int meshDim=ms2[0]->getMeshDimension();
6876   std::vector<const MEDCouplingUMesh *> m1ssm;
6877   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6878   //
6879   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6880   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6881   int fake=0,rk=0;
6882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6883   ret1->alloc(0,1); ret2->alloc(0,1);
6884   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6885     {
6886       if(meshDim!=(*it)->getMeshDimension())
6887         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6888       if(refCoo!=(*it)->getCoords())
6889         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6890       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6891       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6892       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6893       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6894         {
6895           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6896           m1ssmSingleAuto.push_back(singleCell);
6897           m1ssmSingle.push_back(singleCell);
6898           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6899         }
6900     }
6901   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6902   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6903   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6904   for(std::size_t i=0;i<m1ssm.size();i++)
6905     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6906   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6907   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6908   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6909   return ret0.retn();
6910 }
6911
6912 /*!
6913  * This method returns a newly created DataArrayInt instance.
6914  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6915  */
6916 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6917 {
6918   checkFullyDefined();
6919   const int *conn=_nodal_connec->getConstPointer();
6920   const int *connIndex=_nodal_connec_index->getConstPointer();
6921   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6922   for(const int *w=begin;w!=end;w++)
6923     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6924       ret->pushBackSilent(*w);
6925   return ret.retn();
6926 }
6927
6928 /*!
6929  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6930  * are in [0:getNumberOfCells())
6931  */
6932 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6933 {
6934   checkFullyDefined();
6935   const int *conn=_nodal_connec->getConstPointer();
6936   const int *connI=_nodal_connec_index->getConstPointer();
6937   int nbOfCells=getNumberOfCells();
6938   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6939   int *tmp=new int[nbOfCells];
6940   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6941     {
6942       int j=0;
6943       for(const int *i=connI;i!=connI+nbOfCells;i++)
6944         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6945           tmp[std::distance(connI,i)]=j++;
6946     }
6947   DataArrayInt *ret=DataArrayInt::New();
6948   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6949   ret->copyStringInfoFrom(*da);
6950   int *retPtr=ret->getPointer();
6951   const int *daPtr=da->getConstPointer();
6952   int nbOfElems=da->getNbOfElems();
6953   for(int k=0;k<nbOfElems;k++)
6954     retPtr[k]=tmp[daPtr[k]];
6955   delete [] tmp;
6956   return ret;
6957 }
6958
6959 /*!
6960  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6961  * This method \b works \b for mesh sorted by type.
6962  * cells whose ids is in 'idsPerGeoType' array.
6963  * This method conserves coords and name of mesh.
6964  */
6965 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6966 {
6967   std::vector<int> code=getDistributionOfTypes();
6968   std::size_t nOfTypesInThis=code.size()/3;
6969   int sz=0,szOfType=0;
6970   for(std::size_t i=0;i<nOfTypesInThis;i++)
6971     {
6972       if(code[3*i]!=type)
6973         sz+=code[3*i+1];
6974       else
6975         szOfType=code[3*i+1];
6976     }
6977   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6978     if(*work<0 || *work>=szOfType)
6979       {
6980         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6981         oss << ". It should be in [0," << szOfType << ") !";
6982         throw INTERP_KERNEL::Exception(oss.str().c_str());
6983       }
6984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6985   int *idsPtr=idsTokeep->getPointer();
6986   int offset=0;
6987   for(std::size_t i=0;i<nOfTypesInThis;i++)
6988     {
6989       if(code[3*i]!=type)
6990         for(int j=0;j<code[3*i+1];j++)
6991           *idsPtr++=offset+j;
6992       else
6993         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6994       offset+=code[3*i+1];
6995     }
6996   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6997   ret->copyTinyInfoFrom(this);
6998   return ret.retn();
6999 }
7000
7001 /*!
7002  * This method returns a vector of size 'this->getNumberOfCells()'.
7003  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7004  */
7005 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7006 {
7007   int ncell=getNumberOfCells();
7008   std::vector<bool> ret(ncell);
7009   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7010   const int *c=getNodalConnectivity()->getConstPointer();
7011   for(int i=0;i<ncell;i++)
7012     {
7013       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7014       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7015       ret[i]=cm.isQuadratic();
7016     }
7017   return ret;
7018 }
7019
7020 /*!
7021  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7022  */
7023 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7024 {
7025   if(other->getType()!=UNSTRUCTURED)
7026     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7027   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7028   return MergeUMeshes(this,otherC);
7029 }
7030
7031 /*!
7032  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7033  * computed by averaging coordinates of cell nodes, so this method is not a right
7034  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7035  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7036  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7037  *          components. The caller is to delete this array using decrRef() as it is
7038  *          no more needed.
7039  *  \throw If the coordinates array is not set.
7040  *  \throw If the nodal connectivity of cells is not defined.
7041  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7042  */
7043 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7044 {
7045   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7046   int spaceDim=getSpaceDimension();
7047   int nbOfCells=getNumberOfCells();
7048   ret->alloc(nbOfCells,spaceDim);
7049   ret->copyStringInfoFrom(*getCoords());
7050   double *ptToFill=ret->getPointer();
7051   const int *nodal=_nodal_connec->getConstPointer();
7052   const int *nodalI=_nodal_connec_index->getConstPointer();
7053   const double *coor=_coords->getConstPointer();
7054   for(int i=0;i<nbOfCells;i++)
7055     {
7056       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7057       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7058       ptToFill+=spaceDim;
7059     }
7060   return ret.retn();
7061 }
7062
7063 /*!
7064  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7065  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7066  * 
7067  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7068  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7069  * 
7070  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7071  * \throw If \a this is not fully defined (coordinates and connectivity)
7072  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7073  */
7074 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7075 {
7076   checkFullyDefined();
7077   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7078   int spaceDim=getSpaceDimension();
7079   int nbOfCells=getNumberOfCells();
7080   int nbOfNodes=getNumberOfNodes();
7081   ret->alloc(nbOfCells,spaceDim);
7082   double *ptToFill=ret->getPointer();
7083   const int *nodal=_nodal_connec->getConstPointer();
7084   const int *nodalI=_nodal_connec_index->getConstPointer();
7085   const double *coor=_coords->getConstPointer();
7086   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7087     {
7088       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7089       std::fill(ptToFill,ptToFill+spaceDim,0.);
7090       if(type!=INTERP_KERNEL::NORM_POLYHED)
7091         {
7092           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7093             {
7094               if(*conn>=0 && *conn<nbOfNodes)
7095                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7096               else
7097                 {
7098                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7099                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7100                 }
7101             }
7102           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7103           if(nbOfNodesInCell>0)
7104             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7105           else
7106             {
7107               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7108               throw INTERP_KERNEL::Exception(oss.str().c_str());
7109             }
7110         }
7111       else
7112         {
7113           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7114           s.erase(-1);
7115           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7116             {
7117               if(*it>=0 && *it<nbOfNodes)
7118                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7119               else
7120                 {
7121                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7122                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7123                 }
7124             }
7125           if(!s.empty())
7126             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7127           else
7128             {
7129               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7130               throw INTERP_KERNEL::Exception(oss.str().c_str());
7131             }
7132         }
7133     }
7134   return ret.retn();
7135 }
7136
7137 /*!
7138  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7139  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7140  * are specified via an array of cell ids. 
7141  *  \warning Validity of the specified cell ids is not checked! 
7142  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7143  *  \param [in] begin - an array of cell ids of interest.
7144  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7145  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7146  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7147  *          caller is to delete this array using decrRef() as it is no more needed. 
7148  *  \throw If the coordinates array is not set.
7149  *  \throw If the nodal connectivity of cells is not defined.
7150  *
7151  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7152  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7153  */
7154 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7155 {
7156   DataArrayDouble *ret=DataArrayDouble::New();
7157   int spaceDim=getSpaceDimension();
7158   int nbOfTuple=(int)std::distance(begin,end);
7159   ret->alloc(nbOfTuple,spaceDim);
7160   double *ptToFill=ret->getPointer();
7161   double *tmp=new double[spaceDim];
7162   const int *nodal=_nodal_connec->getConstPointer();
7163   const int *nodalI=_nodal_connec_index->getConstPointer();
7164   const double *coor=_coords->getConstPointer();
7165   for(const int *w=begin;w!=end;w++)
7166     {
7167       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7168       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7169       ptToFill+=spaceDim;
7170     }
7171   delete [] tmp;
7172   return ret;
7173 }
7174
7175 /*!
7176  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7177  * 
7178  */
7179 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7180 {
7181   if(!da)
7182     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7183   da->checkAllocated();
7184   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7185   ret->setCoords(da);
7186   int nbOfTuples=da->getNumberOfTuples();
7187   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7188   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7189   c->alloc(2*nbOfTuples,1);
7190   cI->alloc(nbOfTuples+1,1);
7191   int *cp=c->getPointer();
7192   int *cip=cI->getPointer();
7193   *cip++=0;
7194   for(int i=0;i<nbOfTuples;i++)
7195     {
7196       *cp++=INTERP_KERNEL::NORM_POINT1;
7197       *cp++=i;
7198       *cip++=2*(i+1);
7199     }
7200   ret->setConnectivity(c,cI,true);
7201   return ret.retn();
7202 }
7203 /*!
7204  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7205  * Cells and nodes of
7206  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7207  *  \param [in] mesh1 - the first mesh.
7208  *  \param [in] mesh2 - the second mesh.
7209  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7210  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7211  *          is no more needed.
7212  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7213  *  \throw If the coordinates array is not set in none of the meshes.
7214  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7215  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7216  */
7217 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7218 {
7219   std::vector<const MEDCouplingUMesh *> tmp(2);
7220   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7221   return MergeUMeshes(tmp);
7222 }
7223
7224 /*!
7225  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7226  * Cells and nodes of
7227  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7228  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7229  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7230  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7231  *          is no more needed.
7232  *  \throw If \a a.size() == 0.
7233  *  \throw If \a a[ *i* ] == NULL.
7234  *  \throw If the coordinates array is not set in none of the meshes.
7235  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7236  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7237 */
7238 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7239 {
7240   std::size_t sz=a.size();
7241   if(sz==0)
7242     return MergeUMeshesLL(a);
7243   for(std::size_t ii=0;ii<sz;ii++)
7244     if(!a[ii])
7245       {
7246         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7247         throw INTERP_KERNEL::Exception(oss.str().c_str());
7248       }
7249   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7250   std::vector< const MEDCouplingUMesh * > aa(sz);
7251   int spaceDim=-3;
7252   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7253     {
7254       const MEDCouplingUMesh *cur=a[i];
7255       const DataArrayDouble *coo=cur->getCoords();
7256       if(coo)
7257         spaceDim=coo->getNumberOfComponents();
7258     }
7259   if(spaceDim==-3)
7260     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7261   for(std::size_t i=0;i<sz;i++)
7262     {
7263       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7264       aa[i]=bb[i];
7265     }
7266   return MergeUMeshesLL(aa);
7267 }
7268
7269 /// @cond INTERNAL
7270
7271 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7272 {
7273   if(a.empty())
7274     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7275   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7276   int meshDim=(*it)->getMeshDimension();
7277   int nbOfCells=(*it)->getNumberOfCells();
7278   int meshLgth=(*it++)->getMeshLength();
7279   for(;it!=a.end();it++)
7280     {
7281       if(meshDim!=(*it)->getMeshDimension())
7282         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7283       nbOfCells+=(*it)->getNumberOfCells();
7284       meshLgth+=(*it)->getMeshLength();
7285     }
7286   std::vector<const MEDCouplingPointSet *> aps(a.size());
7287   std::copy(a.begin(),a.end(),aps.begin());
7288   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7289   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7290   ret->setCoords(pts);
7291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7292   c->alloc(meshLgth,1);
7293   int *cPtr=c->getPointer();
7294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7295   cI->alloc(nbOfCells+1,1);
7296   int *cIPtr=cI->getPointer();
7297   *cIPtr++=0;
7298   int offset=0;
7299   int offset2=0;
7300   for(it=a.begin();it!=a.end();it++)
7301     {
7302       int curNbOfCell=(*it)->getNumberOfCells();
7303       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7304       const int *curC=(*it)->_nodal_connec->getConstPointer();
7305       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7306       for(int j=0;j<curNbOfCell;j++)
7307         {
7308           const int *src=curC+curCI[j];
7309           *cPtr++=*src++;
7310           for(;src!=curC+curCI[j+1];src++,cPtr++)
7311             {
7312               if(*src!=-1)
7313                 *cPtr=*src+offset2;
7314               else
7315                 *cPtr=-1;
7316             }
7317         }
7318       offset+=curCI[curNbOfCell];
7319       offset2+=(*it)->getNumberOfNodes();
7320     }
7321   //
7322   ret->setConnectivity(c,cI,true);
7323   return ret.retn();
7324 }
7325
7326 /// @endcond
7327
7328 /*!
7329  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7330  * dimension and sharing the node coordinates array.
7331  * All cells of the first mesh precede all cells of the second mesh
7332  * within the result mesh. 
7333  *  \param [in] mesh1 - the first mesh.
7334  *  \param [in] mesh2 - the second mesh.
7335  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7336  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7337  *          is no more needed.
7338  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7339  *  \throw If the meshes do not share the node coordinates array.
7340  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7341  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7342  */
7343 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7344 {
7345   std::vector<const MEDCouplingUMesh *> tmp(2);
7346   tmp[0]=mesh1; tmp[1]=mesh2;
7347   return MergeUMeshesOnSameCoords(tmp);
7348 }
7349
7350 /*!
7351  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7352  * dimension and sharing the node coordinates array.
7353  * All cells of the *i*-th mesh precede all cells of the
7354  * (*i*+1)-th mesh within the result mesh.
7355  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7356  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7357  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7358  *          is no more needed.
7359  *  \throw If \a a.size() == 0.
7360  *  \throw If \a a[ *i* ] == NULL.
7361  *  \throw If the meshes do not share the node coordinates array.
7362  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7363  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7364  */
7365 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7366 {
7367   if(meshes.empty())
7368     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7369   for(std::size_t ii=0;ii<meshes.size();ii++)
7370     if(!meshes[ii])
7371       {
7372         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7373         throw INTERP_KERNEL::Exception(oss.str().c_str());
7374       }
7375   const DataArrayDouble *coords=meshes.front()->getCoords();
7376   int meshDim=meshes.front()->getMeshDimension();
7377   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7378   int meshLgth=0;
7379   int meshIndexLgth=0;
7380   for(;iter!=meshes.end();iter++)
7381     {
7382       if(coords!=(*iter)->getCoords())
7383         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7384       if(meshDim!=(*iter)->getMeshDimension())
7385         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7386       meshLgth+=(*iter)->getMeshLength();
7387       meshIndexLgth+=(*iter)->getNumberOfCells();
7388     }
7389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7390   nodal->alloc(meshLgth,1);
7391   int *nodalPtr=nodal->getPointer();
7392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7393   nodalIndex->alloc(meshIndexLgth+1,1);
7394   int *nodalIndexPtr=nodalIndex->getPointer();
7395   int offset=0;
7396   for(iter=meshes.begin();iter!=meshes.end();iter++)
7397     {
7398       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7399       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7400       int nbOfCells=(*iter)->getNumberOfCells();
7401       int meshLgth2=(*iter)->getMeshLength();
7402       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7403       if(iter!=meshes.begin())
7404         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7405       else
7406         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7407       offset+=meshLgth2;
7408     }
7409   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7410   ret->setName("merge");
7411   ret->setMeshDimension(meshDim);
7412   ret->setConnectivity(nodal,nodalIndex,true);
7413   ret->setCoords(coords);
7414   return ret;
7415 }
7416
7417 /*!
7418  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7419  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7420  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7421  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7422  * New" mode are returned for each input mesh.
7423  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7424  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7425  *          valid values [0,1,2], see zipConnectivityTraducer().
7426  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7427  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7428  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7429  *          no more needed.
7430  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7431  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7432  *          is no more needed.
7433  *  \throw If \a meshes.size() == 0.
7434  *  \throw If \a meshes[ *i* ] == NULL.
7435  *  \throw If the meshes do not share the node coordinates array.
7436  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7437  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7438  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7439  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7440  */
7441 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7442 {
7443   //All checks are delegated to MergeUMeshesOnSameCoords
7444   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7445   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7446   corr.resize(meshes.size());
7447   std::size_t nbOfMeshes=meshes.size();
7448   int offset=0;
7449   const int *o2nPtr=o2n->getConstPointer();
7450   for(std::size_t i=0;i<nbOfMeshes;i++)
7451     {
7452       DataArrayInt *tmp=DataArrayInt::New();
7453       int curNbOfCells=meshes[i]->getNumberOfCells();
7454       tmp->alloc(curNbOfCells,1);
7455       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7456       offset+=curNbOfCells;
7457       tmp->setName(meshes[i]->getName().c_str());
7458       corr[i]=tmp;
7459     }
7460   return ret.retn();
7461 }
7462
7463 /*!
7464  * Makes all given meshes share the nodal connectivity array. The common connectivity
7465  * array is created by concatenating the connectivity arrays of all given meshes. All
7466  * the given meshes must be of the same space dimension but dimension of cells **can
7467  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7468  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7469  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7470  *  \param [in,out] meshes - a vector of meshes to update.
7471  *  \throw If any of \a meshes is NULL.
7472  *  \throw If the coordinates array is not set in any of \a meshes.
7473  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7474  *  \throw If \a meshes are of different space dimension.
7475  */
7476 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7477 {
7478   std::size_t sz=meshes.size();
7479   if(sz==0 || sz==1)
7480     return;
7481   std::vector< const DataArrayDouble * > coords(meshes.size());
7482   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7483   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7484     {
7485       if((*it))
7486         {
7487           (*it)->checkConnectivityFullyDefined();
7488           const DataArrayDouble *coo=(*it)->getCoords();
7489           if(coo)
7490             *it2=coo;
7491           else
7492             {
7493               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7494               oss << " has no coordinate array defined !";
7495               throw INTERP_KERNEL::Exception(oss.str().c_str());
7496             }
7497         }
7498       else
7499         {
7500           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7501           oss << " is null !";
7502           throw INTERP_KERNEL::Exception(oss.str().c_str());
7503         }
7504     }
7505   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7506   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7507   int offset=(*it)->getNumberOfNodes();
7508   (*it++)->setCoords(res);
7509   for(;it!=meshes.end();it++)
7510     {
7511       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7512       (*it)->setCoords(res);
7513       (*it)->shiftNodeNumbersInConn(offset);
7514       offset+=oldNumberOfNodes;
7515     }
7516 }
7517
7518 /*!
7519  * Merges nodes coincident with a given precision within all given meshes that share
7520  * the nodal connectivity array. The given meshes **can be of different** mesh
7521  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7522  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7523  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7524  *  \param [in,out] meshes - a vector of meshes to update.
7525  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7526  *  \throw If any of \a meshes is NULL.
7527  *  \throw If the \a meshes do not share the same node coordinates array.
7528  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7529  */
7530 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7531 {
7532   if(meshes.empty())
7533     return ;
7534   std::set<const DataArrayDouble *> s;
7535   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7536     {
7537       if(*it)
7538         s.insert((*it)->getCoords());
7539       else
7540         {
7541           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 !";
7542           throw INTERP_KERNEL::Exception(oss.str().c_str());
7543         }
7544     }
7545   if(s.size()!=1)
7546     {
7547       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 !";
7548       throw INTERP_KERNEL::Exception(oss.str().c_str());
7549     }
7550   const DataArrayDouble *coo=*(s.begin());
7551   if(!coo)
7552     return;
7553   //
7554   DataArrayInt *comm,*commI;
7555   coo->findCommonTuples(eps,-1,comm,commI);
7556   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7557   int oldNbOfNodes=coo->getNumberOfTuples();
7558   int newNbOfNodes;
7559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7560   if(oldNbOfNodes==newNbOfNodes)
7561     return ;
7562   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7563   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7564     {
7565       (*it)->renumberNodesInConn(o2n->getConstPointer());
7566       (*it)->setCoords(newCoords);
7567     } 
7568 }
7569
7570 /*!
7571  * 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.
7572  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7573  * \param isQuad specifies the policy of connectivity.
7574  * @ret in/out parameter in which the result will be append
7575  */
7576 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7577 {
7578   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7579   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7580   ret.push_back(cm.getExtrudedType());
7581   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7582   switch(flatType)
7583     {
7584     case INTERP_KERNEL::NORM_POINT1:
7585       {
7586         ret.push_back(connBg[1]);
7587         ret.push_back(connBg[1]+nbOfNodesPerLev);
7588         break;
7589       }
7590     case INTERP_KERNEL::NORM_SEG2:
7591       {
7592         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7593         ret.insert(ret.end(),conn,conn+4);
7594         break;
7595       }
7596     case INTERP_KERNEL::NORM_SEG3:
7597       {
7598         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7599         ret.insert(ret.end(),conn,conn+8);
7600         break;
7601       }
7602     case INTERP_KERNEL::NORM_QUAD4:
7603       {
7604         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7605         ret.insert(ret.end(),conn,conn+8);
7606         break;
7607       }
7608     case INTERP_KERNEL::NORM_TRI3:
7609       {
7610         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7611         ret.insert(ret.end(),conn,conn+6);
7612         break;
7613       }
7614     case INTERP_KERNEL::NORM_TRI6:
7615       {
7616         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,
7617                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7618         ret.insert(ret.end(),conn,conn+15);
7619         break;
7620       }
7621     case INTERP_KERNEL::NORM_QUAD8:
7622       {
7623         int conn[20]={
7624           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7625           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7626           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7627         };
7628         ret.insert(ret.end(),conn,conn+20);
7629         break;
7630       }
7631     case INTERP_KERNEL::NORM_POLYGON:
7632       {
7633         std::back_insert_iterator< std::vector<int> > ii(ret);
7634         std::copy(connBg+1,connEnd,ii);
7635         *ii++=-1;
7636         std::reverse_iterator<const int *> rConnBg(connEnd);
7637         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7638         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7639         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7640         for(std::size_t i=0;i<nbOfRadFaces;i++)
7641           {
7642             *ii++=-1;
7643             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7644             std::copy(conn,conn+4,ii);
7645           }
7646         break;
7647       }
7648     default:
7649       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7650     }
7651 }
7652
7653 /*!
7654  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7655  */
7656 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7657 {
7658   double v[3]={0.,0.,0.};
7659   std::size_t sz=std::distance(begin,end);
7660   if(isQuadratic)
7661     sz/=2;
7662   for(std::size_t i=0;i<sz;i++)
7663     {
7664       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];
7665       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7666       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7667     }
7668   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7669 }
7670
7671 /*!
7672  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7673  */
7674 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7675 {
7676   std::vector<std::pair<int,int> > edges;
7677   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7678   const int *bgFace=begin;
7679   for(std::size_t i=0;i<nbOfFaces;i++)
7680     {
7681       const int *endFace=std::find(bgFace+1,end,-1);
7682       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7683       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7684         {
7685           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7686           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7687             return false;
7688           edges.push_back(p1);
7689         }
7690       bgFace=endFace+1;
7691     }
7692   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7693 }
7694
7695 /*!
7696  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7697  */
7698 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7699 {
7700   double vec0[3],vec1[3];
7701   std::size_t sz=std::distance(begin,end);
7702   if(sz%2!=0)
7703     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7704   int nbOfNodes=(int)sz/2;
7705   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7706   const double *pt0=coords+3*begin[0];
7707   const double *pt1=coords+3*begin[nbOfNodes];
7708   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7709   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7710 }
7711
7712 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7713 {
7714   std::size_t sz=std::distance(begin,end);
7715   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7716   std::size_t nbOfNodes(sz/2);
7717   std::copy(begin,end,(int *)tmp);
7718   for(std::size_t j=1;j<nbOfNodes;j++)
7719     {
7720       begin[j]=tmp[nbOfNodes-j];
7721       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7722     }
7723 }
7724
7725 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7726 {
7727   std::size_t sz=std::distance(begin,end);
7728   if(sz!=4)
7729     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7730   double vec0[3],vec1[3];
7731   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7732   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]; 
7733   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;
7734 }
7735
7736 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7737 {
7738   std::size_t sz=std::distance(begin,end);
7739   if(sz!=5)
7740     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7741   double vec0[3];
7742   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7743   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7744   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7745 }
7746
7747 /*!
7748  * 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 ) 
7749  * 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
7750  * a 2D space.
7751  *
7752  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7753  * \param [in] coords the coordinates with nb of components exactly equal to 3
7754  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7755  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7756  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7757  */
7758 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7759 {
7760   int nbFaces=std::count(begin+1,end,-1)+1;
7761   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7762   double *vPtr=v->getPointer();
7763   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7764   double *pPtr=p->getPointer();
7765   const int *stFaceConn=begin+1;
7766   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7767     {
7768       const int *endFaceConn=std::find(stFaceConn,end,-1);
7769       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7770       stFaceConn=endFaceConn+1;
7771     }
7772   pPtr=p->getPointer(); vPtr=v->getPointer();
7773   DataArrayInt *comm1=0,*commI1=0;
7774   v->findCommonTuples(eps,-1,comm1,commI1);
7775   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7776   const int *comm1Ptr=comm1->getConstPointer();
7777   const int *commI1Ptr=commI1->getConstPointer();
7778   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7779   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7780   //
7781   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7782   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7783   mm->finishInsertingCells();
7784   //
7785   for(int i=0;i<nbOfGrps1;i++)
7786     {
7787       int vecId=comm1Ptr[commI1Ptr[i]];
7788       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7789       DataArrayInt *comm2=0,*commI2=0;
7790       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7791       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7792       const int *comm2Ptr=comm2->getConstPointer();
7793       const int *commI2Ptr=commI2->getConstPointer();
7794       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7795       for(int j=0;j<nbOfGrps2;j++)
7796         {
7797           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7798             {
7799               res->insertAtTheEnd(begin,end);
7800               res->pushBackSilent(-1);
7801             }
7802           else
7803             {
7804               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7805               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7806               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7807               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7808               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7809               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7810               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7811               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7812               const int *idsNodePtr=idsNode->getConstPointer();
7813               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];
7814               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7815               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7816               if(std::abs(norm)>eps)
7817                 {
7818                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7819                   mm3->rotate(center,vec,angle);
7820                 }
7821               mm3->changeSpaceDimension(2);
7822               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7823               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7824               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7825               int nbOfCells=mm4->getNumberOfCells();
7826               for(int k=0;k<nbOfCells;k++)
7827                 {
7828                   int l=0;
7829                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7830                     res->pushBackSilent(idsNodePtr[*work]);
7831                   res->pushBackSilent(-1);
7832                 }
7833             }
7834         }
7835     }
7836   res->popBackSilent();
7837 }
7838
7839 /*!
7840  * 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
7841  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7842  * 
7843  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7844  * \param [in] coords coordinates expected to have 3 components.
7845  * \param [in] begin start of the nodal connectivity of the face.
7846  * \param [in] end end of the nodal connectivity (excluded) of the face.
7847  * \param [out] v the normalized vector of size 3
7848  * \param [out] p the pos of plane
7849  */
7850 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7851 {
7852   std::size_t nbPoints=std::distance(begin,end);
7853   if(nbPoints<3)
7854     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7855   double vec[3]={0.,0.,0.};
7856   std::size_t j=0;
7857   bool refFound=false;
7858   for(;j<nbPoints-1 && !refFound;j++)
7859     {
7860       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7861       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7862       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7863       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7864       if(norm>eps)
7865         {
7866           refFound=true;
7867           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7868         }
7869     }
7870   for(std::size_t i=j;i<nbPoints-1;i++)
7871     {
7872       double curVec[3];
7873       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7874       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7875       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7876       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7877       if(norm<eps)
7878         continue;
7879       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7880       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];
7881       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7882       if(norm>eps)
7883         {
7884           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7885           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7886           return ;
7887         }
7888     }
7889   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7890 }
7891
7892 /*!
7893  * This method tries to obtain a well oriented polyhedron.
7894  * If the algorithm fails, an exception will be thrown.
7895  */
7896 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7897 {
7898   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7899   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7900   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7901   isPerm[0]=true;
7902   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7903   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7904   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7905   //
7906   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7907     {
7908       bgFace=begin;
7909       std::size_t smthChanged=0;
7910       for(std::size_t i=0;i<nbOfFaces;i++)
7911         {
7912           endFace=std::find(bgFace+1,end,-1);
7913           nbOfEdgesInFace=std::distance(bgFace,endFace);
7914           if(!isPerm[i])
7915             {
7916               bool b;
7917               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7918                 {
7919                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7920                   std::pair<int,int> p2(p1.second,p1.first);
7921                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7922                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7923                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7924                 }
7925               if(isPerm[i])
7926                 { 
7927                   if(!b)
7928                     std::reverse(bgFace+1,endFace);
7929                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7930                     {
7931                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7932                       std::pair<int,int> p2(p1.second,p1.first);
7933                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7934                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7935                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7936                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7937                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7938                       if(it!=edgesOK.end())
7939                         {
7940                           edgesOK.erase(it);
7941                           edgesFinished.push_back(p1);
7942                         }
7943                       else
7944                         edgesOK.push_back(p1);
7945                     }
7946                 }
7947             }
7948           bgFace=endFace+1;
7949         }
7950       if(smthChanged==0)
7951         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7952     }
7953   if(!edgesOK.empty())
7954     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7955   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7956     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7957       bgFace=begin;
7958       for(std::size_t i=0;i<nbOfFaces;i++)
7959         {
7960           endFace=std::find(bgFace+1,end,-1);
7961           std::reverse(bgFace+1,endFace);
7962           bgFace=endFace+1;
7963         }
7964     }
7965 }
7966
7967 /*!
7968  * This method makes the assumption spacedimension == meshdimension == 2.
7969  * This method works only for linear cells.
7970  * 
7971  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7972  */
7973 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7974 {
7975   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7976     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7977   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7978   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7979   int nbOfNodesExpected=m->getNumberOfNodes();
7980   if(m->getNumberOfCells()!=nbOfNodesExpected)
7981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7983   const int *n2oPtr=n2o->getConstPointer();
7984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7985   m->getReverseNodalConnectivity(revNodal,revNodalI);
7986   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7987   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7988   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7989   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7990   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7991   if(nbOfNodesExpected<1)
7992     return ret.retn();
7993   int prevCell=0;
7994   int prevNode=nodalPtr[nodalIPtr[0]+1];
7995   *work++=n2oPtr[prevNode];
7996   for(int i=1;i<nbOfNodesExpected;i++)
7997     {
7998       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7999         {
8000           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8001           conn.erase(prevNode);
8002           if(conn.size()==1)
8003             {
8004               int curNode=*(conn.begin());
8005               *work++=n2oPtr[curNode];
8006               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8007               shar.erase(prevCell);
8008               if(shar.size()==1)
8009                 {
8010                   prevCell=*(shar.begin());
8011                   prevNode=curNode;
8012                 }
8013               else
8014                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8015             }
8016           else
8017             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8018         }
8019       else
8020         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8021     }
8022   return ret.retn();
8023 }
8024
8025 /*!
8026  * This method makes the assumption spacedimension == meshdimension == 3.
8027  * This method works only for linear cells.
8028  * 
8029  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8030  */
8031 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8032 {
8033   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8035   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8036   const int *conn=m->getNodalConnectivity()->getConstPointer();
8037   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8038   int nbOfCells=m->getNumberOfCells();
8039   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8040   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8041   if(nbOfCells<1)
8042     return ret.retn();
8043   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8044   for(int i=1;i<nbOfCells;i++)
8045     {
8046       *work++=-1;
8047       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8048     }
8049   return ret.retn();
8050 }
8051
8052 /*!
8053  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8054  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8055  */
8056 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8057 {
8058   double *w=zipFrmt;
8059   if(spaceDim==3)
8060     for(int i=0;i<nbOfNodesInCell;i++)
8061       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8062   else if(spaceDim==2)
8063     {
8064       for(int i=0;i<nbOfNodesInCell;i++)
8065         {
8066           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8067           *w++=0.;
8068         }
8069     }
8070   else
8071     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8072 }
8073
8074 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8075 {
8076   int nbOfCells=getNumberOfCells();
8077   if(nbOfCells<=0)
8078     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8079   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};
8080   ofs << "  <" << getVTKDataSetType() << ">\n";
8081   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8082   ofs << "      <PointData>\n" << pointData << std::endl;
8083   ofs << "      </PointData>\n";
8084   ofs << "      <CellData>\n" << cellData << std::endl;
8085   ofs << "      </CellData>\n";
8086   ofs << "      <Points>\n";
8087   if(getSpaceDimension()==3)
8088     _coords->writeVTK(ofs,8,"Points");
8089   else
8090     {
8091       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8092       coo->writeVTK(ofs,8,"Points");
8093     }
8094   ofs << "      </Points>\n";
8095   ofs << "      <Cells>\n";
8096   const int *cPtr=_nodal_connec->getConstPointer();
8097   const int *cIPtr=_nodal_connec_index->getConstPointer();
8098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8099   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8100   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8101   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8102   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8103   int szFaceOffsets=0,szConn=0;
8104   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8105     {
8106       *w2=cPtr[cIPtr[i]];
8107       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8108         {
8109           *w1=-1;
8110           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8111           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8112         }
8113       else
8114         {
8115           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8116           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8117           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8118           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8119           w4=std::copy(c.begin(),c.end(),w4);
8120         }
8121     }
8122   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8123   types->writeVTK(ofs,8,"UInt8","types");
8124   offsets->writeVTK(ofs,8,"Int32","offsets");
8125   if(szFaceOffsets!=0)
8126     {//presence of Polyhedra
8127       connectivity->reAlloc(szConn);
8128       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8129       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8130       w1=faces->getPointer();
8131       for(int i=0;i<nbOfCells;i++)
8132         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8133           {
8134             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8135             *w1++=nbFaces;
8136             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8137             for(int j=0;j<nbFaces;j++)
8138               {
8139                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8140                 *w1++=(int)std::distance(w6,w5);
8141                 w1=std::copy(w6,w5,w1);
8142                 w6=w5+1;
8143               }
8144           }
8145       faces->writeVTK(ofs,8,"Int32","faces");
8146     }
8147   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8148   ofs << "      </Cells>\n";
8149   ofs << "    </Piece>\n";
8150   ofs << "  </" << getVTKDataSetType() << ">\n";
8151 }
8152
8153 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8154 {
8155   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8156   if(_mesh_dim==-2)
8157     { stream << " Not set !"; return ; }
8158   stream << " Mesh dimension : " << _mesh_dim << ".";
8159   if(_mesh_dim==-1)
8160     return ;
8161   if(!_coords)
8162     { stream << " No coordinates set !"; return ; }
8163   if(!_coords->isAllocated())
8164     { stream << " Coordinates set but not allocated !"; return ; }
8165   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8166   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8167   if(!_nodal_connec_index)
8168     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8169   if(!_nodal_connec_index->isAllocated())
8170     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8171   int lgth=_nodal_connec_index->getNumberOfTuples();
8172   int cpt=_nodal_connec_index->getNumberOfComponents();
8173   if(cpt!=1 || lgth<1)
8174     return ;
8175   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8176 }
8177
8178 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8179 {
8180   return std::string("UnstructuredGrid");
8181 }
8182
8183 /*!
8184  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8185  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8186  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8187  * meshes.
8188  *  \param [in] m1 - the first input mesh which is a partitioned object.
8189  *  \param [in] m2 - the second input mesh which is a partition tool.
8190  *  \param [in] eps - precision used to detect coincident mesh entities.
8191  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8192  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8193  *         this array using decrRef() as it is no more needed.
8194  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8195  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8196  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8197  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8198  *         it is no more needed.  
8199  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8200  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8201  *         is no more needed.  
8202  *  \throw If the coordinates array is not set in any of the meshes.
8203  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8204  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8205  */
8206 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8207 {
8208   m1->checkFullyDefined();
8209   m2->checkFullyDefined();
8210   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8211     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8212   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8213   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8214   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8215   std::vector<double> addCoo,addCoordsQuadratic;
8216   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8217   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8218   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8219                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8220   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8221   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8222   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8223   std::vector< std::vector<int> > intersectEdge2;
8224   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8225   subDiv2.clear(); dd5=0; dd6=0;
8226   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8227   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8228   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8229                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8230   //
8231   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8232   addCooDa->alloc((int)(addCoo.size())/2,2);
8233   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8234   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8235   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8236   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8237   std::vector<const DataArrayDouble *> coordss(4);
8238   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8239   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8240   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8245   ret->setConnectivity(conn,connI,true);
8246   ret->setCoords(coo);
8247   cellNb1=c1.retn(); cellNb2=c2.retn();
8248   return ret.retn();
8249 }
8250
8251 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8252                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8253                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8254                                                          const std::vector<double>& addCoords,
8255                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8256 {
8257   static const int SPACEDIM=2;
8258   const double *coo1=m1->getCoords()->getConstPointer();
8259   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8260   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8261   int offset1=m1->getNumberOfNodes();
8262   const double *coo2=m2->getCoords()->getConstPointer();
8263   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8264   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8265   int offset2=offset1+m2->getNumberOfNodes();
8266   int offset3=offset2+((int)addCoords.size())/2;
8267   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8268   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8269   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8270   int ncell1=m1->getNumberOfCells();
8271   crI.push_back(0);
8272   for(int i=0;i<ncell1;i++)
8273     {
8274       std::vector<int> candidates2;
8275       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8276       std::map<INTERP_KERNEL::Node *,int> mapp;
8277       std::map<int,INTERP_KERNEL::Node *> mappRev;
8278       INTERP_KERNEL::QuadraticPolygon pol1;
8279       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8280       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8281       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8282       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8283                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8284       //
8285       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
8286       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8287       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8288       for(it1.first();!it1.finished();it1.next())
8289         edges1.insert(it1.current()->getPtr());
8290       //
8291       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8292       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8293       int ii=0;
8294       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8295         {
8296           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8297           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8298           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8299           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8300                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8301         }
8302       ii=0;
8303       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8304         {
8305           pol1.initLocationsWithOther(pol2s[ii]);
8306           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8307           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8308           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8309         }
8310       if(!edges1.empty())
8311         {
8312           try
8313             {
8314               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8315             }
8316           catch(INTERP_KERNEL::Exception& e)
8317             {
8318               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();
8319               throw INTERP_KERNEL::Exception(oss.str().c_str());
8320             }
8321         }
8322       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8323         (*it).second->decrRef();
8324     }
8325 }
8326
8327 /*!
8328  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8329  * 
8330  */
8331 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8332                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8333                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8334                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8335                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8336 {
8337   static const int SPACEDIM=2;
8338   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8339   desc2=DataArrayInt::New();
8340   descIndx2=DataArrayInt::New();
8341   revDesc2=DataArrayInt::New();
8342   revDescIndx2=DataArrayInt::New();
8343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8345   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8346   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8348   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8349   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8350   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8351   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8352   int ncell1=m1Desc->getNumberOfCells();
8353   int ncell2=m2Desc->getNumberOfCells();
8354   intersectEdge1.resize(ncell1);
8355   colinear2.resize(ncell2);
8356   subDiv2.resize(ncell2);
8357   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8358   std::vector<int> candidates1(1);
8359   int offset1=m1->getNumberOfNodes();
8360   int offset2=offset1+m2->getNumberOfNodes();
8361   for(int i=0;i<ncell1;i++)
8362     {
8363       std::vector<int> candidates2;
8364       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8365       if(!candidates2.empty())
8366         {
8367           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8368           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8369           candidates1[0]=i;
8370           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8371           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8372           delete pol2;
8373           delete pol1;
8374         }
8375       else
8376         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8377     }
8378   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8379   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8380 }
8381
8382 /*!
8383  * This method performs the 2nd step of Partition of 2D mesh.
8384  * This method has 4 inputs :
8385  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8386  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8387  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8388  * 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'
8389  * \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'
8390  * \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.
8391  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8392  */
8393 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)
8394 {
8395   int offset1=m1->getNumberOfNodes();
8396   int ncell=m2->getNumberOfCells();
8397   const int *c=m2->getNodalConnectivity()->getConstPointer();
8398   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8399   const double *coo=m2->getCoords()->getConstPointer();
8400   const double *cooBis=m1->getCoords()->getConstPointer();
8401   int offset2=offset1+m2->getNumberOfNodes();
8402   intersectEdge.resize(ncell);
8403   for(int i=0;i<ncell;i++,cI++)
8404     {
8405       const std::vector<int>& divs=subDiv[i];
8406       int nnode=cI[1]-cI[0]-1;
8407       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8408       std::map<INTERP_KERNEL::Node *, int> mapp22;
8409       for(int j=0;j<nnode;j++)
8410         {
8411           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8412           int nnid=c[(*cI)+j+1];
8413           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8414           mapp22[nn]=nnid+offset1;
8415         }
8416       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8417       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8418         ((*it).second.first)->decrRef();
8419       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8420       std::map<INTERP_KERNEL::Node *,int> mapp3;
8421       for(std::size_t j=0;j<divs.size();j++)
8422         {
8423           int id=divs[j];
8424           INTERP_KERNEL::Node *tmp=0;
8425           if(id<offset1)
8426             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8427           else if(id<offset2)
8428             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8429           else
8430             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8431           addNodes[j]=tmp;
8432           mapp3[tmp]=id;
8433         }
8434       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8435       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8436         (*it)->decrRef();
8437       e->decrRef();
8438     }
8439 }
8440
8441 /*!
8442  * 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).
8443  * 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
8444  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8445  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8446  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8447  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8448  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8449  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8450  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8451  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8452  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8453  * \param [out] cut3DSuf input/output param.
8454  */
8455 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8456                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8457                                                    const int *desc, const int *descIndx, 
8458                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8459 {
8460   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8461   int nbOf3DSurfCell=(int)cut3DSurf.size();
8462   for(int i=0;i<nbOf3DSurfCell;i++)
8463     {
8464       std::vector<int> res;
8465       int offset=descIndx[i];
8466       int nbOfSeg=descIndx[i+1]-offset;
8467       for(int j=0;j<nbOfSeg;j++)
8468         {
8469           int edgeId=desc[offset+j];
8470           int status=cut3DCurve[edgeId];
8471           if(status!=-2)
8472             {
8473               if(status>-1)
8474                 res.push_back(status);
8475               else
8476                 {
8477                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8478                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8479                 }
8480             }
8481         }
8482       switch(res.size())
8483         {
8484         case 2:
8485           {
8486             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8487             break;
8488           }
8489         case 1:
8490         case 0:
8491           {
8492             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8493             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8494             if(res.size()==2)
8495               {
8496                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8497               }
8498             else
8499               {
8500                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8501               }
8502             break;
8503           }
8504         default:
8505           {// case when plane is on a multi colinear edge of a polyhedron
8506             if((int)res.size()==2*nbOfSeg)
8507               {
8508                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8509               }
8510             else
8511               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8512           }
8513         }
8514     }
8515 }
8516
8517 /*!
8518  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8519  * 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).
8520  * 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
8521  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8522  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8523  * \param desc is the descending connectivity 3D->3DSurf
8524  * \param descIndx is the descending connectivity index 3D->3DSurf
8525  */
8526 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8527                                                   const int *desc, const int *descIndx,
8528                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8529 {
8530   checkFullyDefined();
8531   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8532     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8533   const int *nodal3D=_nodal_connec->getConstPointer();
8534   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8535   int nbOfCells=getNumberOfCells();
8536   for(int i=0;i<nbOfCells;i++)
8537     {
8538       std::map<int, std::set<int> > m;
8539       int offset=descIndx[i];
8540       int nbOfFaces=descIndx[i+1]-offset;
8541       int start=-1;
8542       int end=-1;
8543       for(int j=0;j<nbOfFaces;j++)
8544         {
8545           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8546           if(p.first!=-1 && p.second!=-1)
8547             {
8548               if(p.first!=-2)
8549                 {
8550                   start=p.first; end=p.second;
8551                   m[p.first].insert(p.second);
8552                   m[p.second].insert(p.first);
8553                 }
8554               else
8555                 {
8556                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8557                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8558                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8559                   INTERP_KERNEL::NormalizedCellType cmsId;
8560                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8561                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8562                   for(unsigned k=0;k<nbOfNodesSon;k++)
8563                     {
8564                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8565                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8566                     }
8567                 }
8568             }
8569         }
8570       if(m.empty())
8571         continue;
8572       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8573       int prev=end;
8574       while(end!=start)
8575         {
8576           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8577           const std::set<int>& s=(*it).second;
8578           std::set<int> s2; s2.insert(prev);
8579           std::set<int> s3;
8580           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8581           if(s3.size()==1)
8582             {
8583               int val=*s3.begin();
8584               conn.push_back(start);
8585               prev=start;
8586               start=val;
8587             }
8588           else
8589             start=end;
8590         }
8591       conn.push_back(end);
8592       if(conn.size()>3)
8593         {
8594           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8595           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8596           cellIds->pushBackSilent(i);
8597         }
8598     }
8599 }
8600
8601 /*!
8602  * 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
8603  * 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
8604  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8605  * 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
8606  * 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.
8607  * 
8608  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8609  */
8610 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8611 {
8612   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8613   if(sz>=4)
8614     {
8615       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8616       if(cm.getDimension()==2)
8617         {
8618           const int *node=nodalConnBg+1;
8619           int startNode=*node++;
8620           double refX=coords[2*startNode];
8621           for(;node!=nodalConnEnd;node++)
8622             {
8623               if(coords[2*(*node)]<refX)
8624                 {
8625                   startNode=*node;
8626                   refX=coords[2*startNode];
8627                 }
8628             }
8629           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8630           refX=1e300;
8631           double tmp1;
8632           double tmp2[2];
8633           double angle0=-M_PI/2;
8634           //
8635           int nextNode=-1;
8636           int prevNode=-1;
8637           double resRef;
8638           double angleNext=0.;
8639           while(nextNode!=startNode)
8640             {
8641               nextNode=-1;
8642               resRef=1e300;
8643               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8644                 {
8645                   if(*node!=tmpOut.back() && *node!=prevNode)
8646                     {
8647                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8648                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8649                       double res;
8650                       if(angleM<=angle0)
8651                         res=angle0-angleM;
8652                       else
8653                         res=angle0-angleM+2.*M_PI;
8654                       if(res<resRef)
8655                         {
8656                           nextNode=*node;
8657                           resRef=res;
8658                           angleNext=angleM;
8659                         }
8660                     }
8661                 }
8662               if(nextNode!=startNode)
8663                 {
8664                   angle0=angleNext-M_PI;
8665                   if(angle0<-M_PI)
8666                     angle0+=2*M_PI;
8667                   prevNode=tmpOut.back();
8668                   tmpOut.push_back(nextNode);
8669                 }
8670             }
8671           std::vector<int> tmp3(2*(sz-1));
8672           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8673           std::copy(nodalConnBg+1,nodalConnEnd,it);
8674           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8675             {
8676               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8677               return false;
8678             }
8679           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8680             {
8681               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8682               return false;
8683             }
8684           else
8685             {
8686               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8687               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8688               return true;
8689             }
8690         }
8691       else
8692         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8693     }
8694   else
8695     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8696 }
8697
8698 /*!
8699  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8700  * 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.
8701  * 
8702  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8703  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8704  * \param [in,out] arr array in which the remove operation will be done.
8705  * \param [in,out] arrIndx array in the remove operation will modify
8706  * \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])
8707  * \return true if \b arr and \b arrIndx have been modified, false if not.
8708  */
8709 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8710 {
8711   if(!arrIndx || !arr)
8712     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8713   if(offsetForRemoval<0)
8714     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8715   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8716   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8717   int *arrIPtr=arrIndx->getPointer();
8718   *arrIPtr++=0;
8719   int previousArrI=0;
8720   const int *arrPtr=arr->getConstPointer();
8721   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8722   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8723     {
8724       if(*arrIPtr-previousArrI>offsetForRemoval)
8725         {
8726           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8727             {
8728               if(s.find(*work)==s.end())
8729                 arrOut.push_back(*work);
8730             }
8731         }
8732       previousArrI=*arrIPtr;
8733       *arrIPtr=(int)arrOut.size();
8734     }
8735   if(arr->getNumberOfTuples()==(int)arrOut.size())
8736     return false;
8737   arr->alloc((int)arrOut.size(),1);
8738   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8739   return true;
8740 }
8741
8742 /*!
8743  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8744  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8745  * The selection of extraction is done standardly in new2old format.
8746  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8747  *
8748  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8749  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8750  * \param [in] arrIn arr origin array from which the extraction will be done.
8751  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8752  * \param [out] arrOut the resulting array
8753  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8754  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8755  */
8756 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8757                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8758 {
8759   if(!arrIn || !arrIndxIn)
8760     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8761   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8762   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8763     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8764   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8765   const int *arrInPtr=arrIn->getConstPointer();
8766   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8767   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8768   if(nbOfGrps<0)
8769     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8770   int maxSizeOfArr=arrIn->getNumberOfTuples();
8771   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8772   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8773   arrIo->alloc((int)(sz+1),1);
8774   const int *idsIt=idsOfSelectBg;
8775   int *work=arrIo->getPointer();
8776   *work++=0;
8777   int lgth=0;
8778   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8779     {
8780       if(*idsIt>=0 && *idsIt<nbOfGrps)
8781         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8782       else
8783         {
8784           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8785           throw INTERP_KERNEL::Exception(oss.str().c_str());
8786         }
8787       if(lgth>=work[-1])
8788         *work=lgth;
8789       else
8790         {
8791           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8792           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8793           throw INTERP_KERNEL::Exception(oss.str().c_str());
8794         }
8795     }
8796   arro->alloc(lgth,1);
8797   work=arro->getPointer();
8798   idsIt=idsOfSelectBg;
8799   for(std::size_t i=0;i<sz;i++,idsIt++)
8800     {
8801       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8802         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8803       else
8804         {
8805           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8806           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8807           throw INTERP_KERNEL::Exception(oss.str().c_str());
8808         }
8809     }
8810   arrOut=arro.retn();
8811   arrIndexOut=arrIo.retn();
8812 }
8813
8814 /*!
8815  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8816  * 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 ).
8817  * The selection of extraction is done standardly in new2old format.
8818  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8819  *
8820  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8821  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8822  * \param [in] arrIn arr origin array from which the extraction will be done.
8823  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8824  * \param [out] arrOut the resulting array
8825  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8826  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8827  */
8828 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8829                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8830 {
8831   if(!arrIn || !arrIndxIn)
8832     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8833   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8834   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8835     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8836   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8837   const int *arrInPtr=arrIn->getConstPointer();
8838   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8839   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8840   if(nbOfGrps<0)
8841     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8842   int maxSizeOfArr=arrIn->getNumberOfTuples();
8843   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8845   arrIo->alloc((int)(sz+1),1);
8846   int idsIt=idsOfSelectStart;
8847   int *work=arrIo->getPointer();
8848   *work++=0;
8849   int lgth=0;
8850   for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8851     {
8852       if(idsIt>=0 && idsIt<nbOfGrps)
8853         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8854       else
8855         {
8856           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8857           throw INTERP_KERNEL::Exception(oss.str().c_str());
8858         }
8859       if(lgth>=work[-1])
8860         *work=lgth;
8861       else
8862         {
8863           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8864           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8865           throw INTERP_KERNEL::Exception(oss.str().c_str());
8866         }
8867     }
8868   arro->alloc(lgth,1);
8869   work=arro->getPointer();
8870   idsIt=idsOfSelectStart;
8871   for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8872     {
8873       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8874         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8875       else
8876         {
8877           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8878           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8879           throw INTERP_KERNEL::Exception(oss.str().c_str());
8880         }
8881     }
8882   arrOut=arro.retn();
8883   arrIndexOut=arrIo.retn();
8884 }
8885
8886 /*!
8887  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8888  * 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
8889  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8890  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8891  *
8892  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8893  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8894  * \param [in] arrIn arr origin array from which the extraction will be done.
8895  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8896  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8897  * \param [in] srcArrIndex index array of \b srcArr
8898  * \param [out] arrOut the resulting array
8899  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8900  * 
8901  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8902  */
8903 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8904                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8905                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8906 {
8907   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8908     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8909   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8910   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8911   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8912   std::vector<bool> v(nbOfTuples,true);
8913   int offset=0;
8914   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8915   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8916   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8917     {
8918       if(*it>=0 && *it<nbOfTuples)
8919         {
8920           v[*it]=false;
8921           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8922         }
8923       else
8924         {
8925           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8926           throw INTERP_KERNEL::Exception(oss.str().c_str());
8927         }
8928     }
8929   srcArrIndexPtr=srcArrIndex->getConstPointer();
8930   arrIo->alloc(nbOfTuples+1,1);
8931   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8932   const int *arrInPtr=arrIn->getConstPointer();
8933   const int *srcArrPtr=srcArr->getConstPointer();
8934   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8935   int *arroPtr=arro->getPointer();
8936   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8937     {
8938       if(v[ii])
8939         {
8940           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8941           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8942         }
8943       else
8944         {
8945           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8946           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8947           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8948         }
8949     }
8950   arrOut=arro.retn();
8951   arrIndexOut=arrIo.retn();
8952 }
8953
8954 /*!
8955  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8956  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8957  *
8958  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8959  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8960  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8961  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8962  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8963  * \param [in] srcArrIndex index array of \b srcArr
8964  * 
8965  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8966  */
8967 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8968                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8969 {
8970   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8971     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8972   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8973   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8974   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8975   int *arrInOutPtr=arrInOut->getPointer();
8976   const int *srcArrPtr=srcArr->getConstPointer();
8977   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8978     {
8979       if(*it>=0 && *it<nbOfTuples)
8980         {
8981           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8982             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8983           else
8984             {
8985               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] !";
8986               throw INTERP_KERNEL::Exception(oss.str().c_str());
8987             }
8988         }
8989       else
8990         {
8991           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8992           throw INTERP_KERNEL::Exception(oss.str().c_str());
8993         }
8994     }
8995 }
8996
8997 /*!
8998  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8999  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9000  * 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]].
9001  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9002  * A negative value in \b arrIn means that it is ignored.
9003  * 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.
9004  * 
9005  * \param [in] arrIn arr origin array from which the extraction will be done.
9006  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9007  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9008  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9009  */
9010 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9011 {
9012   int seed=0,nbOfDepthPeelingPerformed=0;
9013   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9014 }
9015
9016 /*!
9017  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9018  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9019  * 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]].
9020  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9021  * A negative value in \b arrIn means that it is ignored.
9022  * 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.
9023  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9024  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9025  * \param [in] arrIn arr origin array from which the extraction will be done.
9026  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9027  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9028  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9029  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9030  * \sa MEDCouplingUMesh::partitionBySpreadZone
9031  */
9032 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9033 {
9034   nbOfDepthPeelingPerformed=0;
9035   if(!arrIndxIn)
9036     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9037   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9038   if(nbOfTuples<=0)
9039     {
9040       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9041       return ret;
9042     }
9043   //
9044   std::vector<bool> fetched(nbOfTuples,false);
9045   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9046 }
9047
9048 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)
9049 {
9050   nbOfDepthPeelingPerformed=0;
9051   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9052     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9053   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9054   std::vector<bool> fetched2(nbOfTuples,false);
9055   int i=0;
9056   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9057     {
9058       if(*seedElt>=0 && *seedElt<nbOfTuples)
9059         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9060       else
9061         { 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()); }
9062     }
9063   const int *arrInPtr=arrIn->getConstPointer();
9064   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9065   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9066   std::vector<int> idsToFetch1(seedBg,seedEnd);
9067   std::vector<int> idsToFetch2;
9068   std::vector<int> *idsToFetch=&idsToFetch1;
9069   std::vector<int> *idsToFetchOther=&idsToFetch2;
9070   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9071     {
9072       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9073         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9074           if(!fetched[*it2])
9075             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9076       std::swap(idsToFetch,idsToFetchOther);
9077       idsToFetchOther->clear();
9078       nbOfDepthPeelingPerformed++;
9079     }
9080   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9081   i=0;
9082   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9083   int *retPtr=ret->getPointer();
9084   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9085     if(*it)
9086       *retPtr++=i;
9087   return ret.retn();
9088 }
9089
9090 /*!
9091  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9092  * 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
9093  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9094  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9095  *
9096  * \param [in] start begin of set of ids of the input extraction (included)
9097  * \param [in] end end of set of ids of the input extraction (excluded)
9098  * \param [in] step step of the set of ids in range mode.
9099  * \param [in] arrIn arr origin array from which the extraction will be done.
9100  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9101  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9102  * \param [in] srcArrIndex index array of \b srcArr
9103  * \param [out] arrOut the resulting array
9104  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9105  * 
9106  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9107  */
9108 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9109                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9110                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9111 {
9112   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9114   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9115   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9116   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9117   int offset=0;
9118   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9119   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9120   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9121   int it=start;
9122   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9123     {
9124       if(it>=0 && it<nbOfTuples)
9125         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9126       else
9127         {
9128           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9129           throw INTERP_KERNEL::Exception(oss.str().c_str());
9130         }
9131     }
9132   srcArrIndexPtr=srcArrIndex->getConstPointer();
9133   arrIo->alloc(nbOfTuples+1,1);
9134   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9135   const int *arrInPtr=arrIn->getConstPointer();
9136   const int *srcArrPtr=srcArr->getConstPointer();
9137   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9138   int *arroPtr=arro->getPointer();
9139   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9140     {
9141       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9142       if(pos<0)
9143         {
9144           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9145           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9146         }
9147       else
9148         {
9149           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9150           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9151         }
9152     }
9153   arrOut=arro.retn();
9154   arrIndexOut=arrIo.retn();
9155 }
9156
9157 /*!
9158  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9159  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9160  *
9161  * \param [in] start begin of set of ids of the input extraction (included)
9162  * \param [in] end end of set of ids of the input extraction (excluded)
9163  * \param [in] step step of the set of ids in range mode.
9164  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9165  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9166  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9167  * \param [in] srcArrIndex index array of \b srcArr
9168  * 
9169  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9170  */
9171 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9172                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9173 {
9174   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9175     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9176   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9177   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9178   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9179   int *arrInOutPtr=arrInOut->getPointer();
9180   const int *srcArrPtr=srcArr->getConstPointer();
9181   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9182   int it=start;
9183   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9184     {
9185       if(it>=0 && it<nbOfTuples)
9186         {
9187           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9188             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9189           else
9190             {
9191               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9192               throw INTERP_KERNEL::Exception(oss.str().c_str());
9193             }
9194         }
9195       else
9196         {
9197           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9198           throw INTERP_KERNEL::Exception(oss.str().c_str());
9199         }
9200     }
9201 }
9202
9203 /*!
9204  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9205  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9206  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9207  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9208  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9209  * 
9210  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9211  */
9212 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9213 {
9214   checkFullyDefined();
9215   int mdim=getMeshDimension();
9216   int spaceDim=getSpaceDimension();
9217   if(mdim!=spaceDim)
9218     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9219   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9220   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9221   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9222   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9223   ret->setCoords(getCoords());
9224   ret->allocateCells((int)partition.size());
9225   //
9226   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9227     {
9228       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9229       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9230       switch(mdim)
9231         {
9232         case 2:
9233           cell=tmp->buildUnionOf2DMesh();
9234           break;
9235         case 3:
9236           cell=tmp->buildUnionOf3DMesh();
9237           break;
9238         default:
9239           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9240         }
9241       
9242       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9243     }
9244   //
9245   ret->finishInsertingCells();
9246   return ret.retn();
9247 }
9248
9249 /*!
9250  * This method partitions \b this into contiguous zone.
9251  * This method only needs a well defined connectivity. Coordinates are not considered here.
9252  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9253  */
9254 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9255 {
9256   int nbOfCellsCur=getNumberOfCells();
9257   std::vector<DataArrayInt *> ret;
9258   if(nbOfCellsCur<=0)
9259     return ret;
9260   DataArrayInt *neigh=0,*neighI=0;
9261   computeNeighborsOfCells(neigh,neighI);
9262   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9263   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9264   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9265   int seed=0;
9266   while(seed<nbOfCellsCur)
9267     {
9268       int nbOfPeelPerformed=0;
9269       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9270       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9271     }
9272   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9273     ret.push_back((*it).retn());
9274   return ret;
9275 }
9276
9277 /*!
9278  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9279  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9280  *
9281  * \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.
9282  * \return a newly allocated DataArrayInt to be managed by the caller.
9283  * \throw In case of \a code has not the right format (typically of size 3*n)
9284  */
9285 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9286 {
9287   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9288   std::size_t nb=code.size()/3;
9289   if(code.size()%3!=0)
9290     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9291   ret->alloc((int)nb,2);
9292   int *retPtr=ret->getPointer();
9293   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9294     {
9295       retPtr[0]=code[3*i+2];
9296       retPtr[1]=code[3*i+2]+code[3*i+1];
9297     }
9298   return ret.retn();
9299 }
9300
9301 /*!
9302  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9303  * All cells in \a this are expected to be linear 3D cells.
9304  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9305  * It leads to an increase to number of cells.
9306  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9307  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
9308  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9309  *
9310  * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells.
9311  *                      For all other cells, the splitting policy will be ignored.
9312  * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added. 
9313  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9314  *          an id of old cell producing it. The caller is to delete this array using
9315  *         decrRef() as it is no more needed.
9316  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9317  * 
9318  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9319  * \throw If \a this is not fully constituted with linear 3D cells.
9320  * \sa MEDCouplingUMesh::simplexize
9321  */
9322 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const throw(INTERP_KERNEL::Exception)
9323 {
9324   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9325   checkConnectivityFullyDefined();
9326   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9327     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9328   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9329   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
9330   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9331   int *retPt(ret->getPointer());
9332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9333   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9334   const int *oldc(_nodal_connec->begin());
9335   const int *oldci(_nodal_connec_index->begin());
9336   const double *coords(_coords->begin());
9337   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9338     {
9339       std::vector<int> a; std::vector<double> b;
9340       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9341       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9342       const int *aa(&a[0]);
9343       if(!b.empty())
9344         {
9345           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9346             if(*it<0)
9347               *it=(-(*(it))-1+nbNodes);
9348           addPts->insertAtTheEnd(b.begin(),b.end());
9349           nbNodes+=(int)b.size()/3;
9350         }
9351       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9352         newConn->insertAtTheEnd(aa,aa+4);
9353     }
9354   if(!addPts->empty())
9355     {
9356       addPts->rearrange(3);
9357       nbOfAdditionalPoints=addPts->getNumberOfTuples();
9358       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9359       ret0->setCoords(addPts);
9360     }
9361   else
9362     {
9363       nbOfAdditionalPoints=0;
9364       ret0->setCoords(getCoords());
9365     }
9366   ret0->setNodalConnectivity(newConn);
9367   //
9368   ret->computeOffsets2();
9369   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9370   return ret0.retn();
9371 }
9372
9373 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9374                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9375 {
9376   if(mesh)
9377     {
9378       mesh->incrRef();
9379       _nb_cell=mesh->getNumberOfCells();
9380     }
9381 }
9382
9383 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9384 {
9385   if(_mesh)
9386     _mesh->decrRef();
9387   if(_own_cell)
9388     delete _cell;
9389 }
9390
9391 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9392                                                                                                                                _own_cell(false),_cell_id(bg-1),
9393                                                                                                                                _nb_cell(end)
9394 {
9395   if(mesh)
9396     mesh->incrRef();
9397 }
9398
9399 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9400 {
9401   _cell_id++;
9402   if(_cell_id<_nb_cell)
9403     {
9404       _cell->next();
9405       return _cell;
9406     }
9407   else
9408     return 0;
9409 }
9410
9411 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9412 {
9413   if(_mesh)
9414     _mesh->incrRef();
9415 }
9416
9417 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9418 {
9419   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9420 }
9421
9422 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9423 {
9424   if(_mesh)
9425     _mesh->decrRef();
9426 }
9427
9428 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9429                                                                                                                                                                   _itc(itc),
9430                                                                                                                                                                   _bg(bg),_end(end)
9431 {
9432   if(_mesh)
9433     _mesh->incrRef();
9434 }
9435
9436 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9437 {
9438   if(_mesh)
9439     _mesh->decrRef();
9440 }
9441
9442 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9443 {
9444   return _type;
9445 }
9446
9447 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9448 {
9449   return _end-_bg;
9450 }
9451
9452 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9453 {
9454   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9455 }
9456
9457 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9458 {
9459   if(mesh)
9460     {
9461       mesh->incrRef();
9462       _nb_cell=mesh->getNumberOfCells();
9463     }
9464 }
9465
9466 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9467 {
9468   if(_mesh)
9469     _mesh->decrRef();
9470   delete _cell;
9471 }
9472
9473 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9474 {
9475   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9476   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9477   if(_cell_id<_nb_cell)
9478     {
9479       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9480       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9481       int startId=_cell_id;
9482       _cell_id+=nbOfElems;
9483       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9484     }
9485   else
9486     return 0;
9487 }
9488
9489 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9490 {
9491   if(mesh)
9492     {
9493       _conn=mesh->getNodalConnectivity()->getPointer();
9494       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9495     }
9496 }
9497
9498 void MEDCouplingUMeshCell::next()
9499 {
9500   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9501     {
9502       _conn+=_conn_lgth;
9503       _conn_indx++;
9504     }
9505   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9506 }
9507
9508 std::string MEDCouplingUMeshCell::repr() const
9509 {
9510   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9511     {
9512       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9513       oss << " : ";
9514       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9515       return oss.str();
9516     }
9517   else
9518     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9519 }
9520
9521 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9522 {
9523   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9524     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9525   else
9526     return INTERP_KERNEL::NORM_ERROR;
9527 }
9528
9529 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9530 {
9531   lgth=_conn_lgth;
9532   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9533     return _conn;
9534   else
9535     return 0;
9536 }