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 * - newly created object (to be managed by the caller) \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),kk(0);
6202       for(int j=0;j<nbOfNodesForCell;j++)
6203         {
6204           int nodeId=conn[offset+j];
6205           if(nodeId>=0 && nodeId<nbOfNodes)
6206             {
6207               for(int k=0;k<spaceDim;k++)
6208                 {
6209                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6210                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6211                 }
6212               kk++;
6213             }
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   return ret.retn();
6222 }
6223
6224 /// @cond INTERNAL
6225
6226 namespace ParaMEDMEMImpl
6227 {
6228   class ConnReader
6229   {
6230   public:
6231     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6232     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6233   private:
6234     const int *_conn;
6235     int _val;
6236   };
6237
6238   class ConnReader2
6239   {
6240   public:
6241     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6242     bool operator() (const int& pos) { return _conn[pos]==_val; }
6243   private:
6244     const int *_conn;
6245     int _val;
6246   };
6247 }
6248
6249 /// @endcond
6250
6251 /*!
6252  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6253  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6254  * \a this is composed in cell types.
6255  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6256  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6257  * This parameter is kept only for compatibility with other methode listed above.
6258  */
6259 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6260 {
6261   checkConnectivityFullyDefined();
6262   const int *conn=_nodal_connec->getConstPointer();
6263   const int *connI=_nodal_connec_index->getConstPointer();
6264   const int *work=connI;
6265   int nbOfCells=getNumberOfCells();
6266   std::size_t n=getAllTypes().size();
6267   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6268   std::set<INTERP_KERNEL::NormalizedCellType> types;
6269   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6270     {
6271       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6272       if(types.find(typ)!=types.end())
6273         {
6274           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6275           oss << " is not contiguous !";
6276           throw INTERP_KERNEL::Exception(oss.str().c_str());
6277         }
6278       types.insert(typ);
6279       ret[3*i]=typ;
6280       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6281       ret[3*i+1]=(int)std::distance(work,work2);
6282       work=work2;
6283     }
6284   return ret;
6285 }
6286
6287 /*!
6288  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6289  * only for types cell, type node is not managed.
6290  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6291  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6292  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6293  * If 2 or more same geometric type is in \a code and exception is thrown too.
6294  *
6295  * This method firstly checks
6296  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6297  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6298  * an exception is thrown too.
6299  * 
6300  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6301  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6302  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6303  */
6304 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6305 {
6306   if(code.empty())
6307     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6308   std::size_t sz=code.size();
6309   std::size_t n=sz/3;
6310   if(sz%3!=0)
6311     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6312   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6313   int nb=0;
6314   bool isNoPflUsed=true;
6315   for(std::size_t i=0;i<n;i++)
6316     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6317       {
6318         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6319         nb+=code[3*i+1];
6320         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6321           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6322         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6323       }
6324   if(types.size()!=n)
6325     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6326   if(isNoPflUsed)
6327     {
6328       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6329         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6330       if(types.size()==_types.size())
6331         return 0;
6332     }
6333   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6334   ret->alloc(nb,1);
6335   int *retPtr=ret->getPointer();
6336   const int *connI=_nodal_connec_index->getConstPointer();
6337   const int *conn=_nodal_connec->getConstPointer();
6338   int nbOfCells=getNumberOfCells();
6339   const int *i=connI;
6340   int kk=0;
6341   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6342     {
6343       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6344       int offset=(int)std::distance(connI,i);
6345       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6346       int nbOfCellsOfCurType=(int)std::distance(i,j);
6347       if(code[3*kk+2]==-1)
6348         for(int k=0;k<nbOfCellsOfCurType;k++)
6349           *retPtr++=k+offset;
6350       else
6351         {
6352           int idInIdsPerType=code[3*kk+2];
6353           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6354             {
6355               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6356               if(zePfl)
6357                 {
6358                   zePfl->checkAllocated();
6359                   if(zePfl->getNumberOfComponents()==1)
6360                     {
6361                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6362                         {
6363                           if(*k>=0 && *k<nbOfCellsOfCurType)
6364                             *retPtr=(*k)+offset;
6365                           else
6366                             {
6367                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6368                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6369                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6370                             }
6371                         }
6372                     }
6373                   else
6374                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6375                 }
6376               else
6377                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6378             }
6379           else
6380             {
6381               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6382               oss << " should be in [0," << idsPerType.size() << ") !";
6383               throw INTERP_KERNEL::Exception(oss.str().c_str());
6384             }
6385         }
6386       i=j;
6387     }
6388   return ret.retn();
6389 }
6390
6391 /*!
6392  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6393  * 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.
6394  * 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.
6395  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6396  * 
6397  * \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.
6398  * \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,
6399  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6400  * \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.
6401  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6402  * \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
6403  */
6404 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6405 {
6406   if(!profile)
6407     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6408   if(profile->getNumberOfComponents()!=1)
6409     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6410   checkConnectivityFullyDefined();
6411   const int *conn=_nodal_connec->getConstPointer();
6412   const int *connI=_nodal_connec_index->getConstPointer();
6413   int nbOfCells=getNumberOfCells();
6414   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6415   std::vector<int> typeRangeVals(1);
6416   for(const int *i=connI;i!=connI+nbOfCells;)
6417     {
6418       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6419       if(std::find(types.begin(),types.end(),curType)!=types.end())
6420         {
6421           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6422         }
6423       types.push_back(curType);
6424       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6425       typeRangeVals.push_back((int)std::distance(connI,i));
6426     }
6427   //
6428   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6429   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6433   //
6434   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6435   code.resize(3*nbOfCastsFinal);
6436   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6437   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6438   for(int i=0;i<nbOfCastsFinal;i++)
6439     {
6440       int castId=castsPresent->getIJ(i,0);
6441       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6442       idsInPflPerType2.push_back(tmp3);
6443       code[3*i]=(int)types[castId];
6444       code[3*i+1]=tmp3->getNumberOfTuples();
6445       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6446       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6447         {
6448           tmp4->copyStringInfoFrom(*profile);
6449           idsPerType2.push_back(tmp4);
6450           code[3*i+2]=(int)idsPerType2.size()-1;
6451         }
6452       else
6453         {
6454           code[3*i+2]=-1;
6455         }
6456     }
6457   std::size_t sz2=idsInPflPerType2.size();
6458   idsInPflPerType.resize(sz2);
6459   for(std::size_t i=0;i<sz2;i++)
6460     {
6461       DataArrayInt *locDa=idsInPflPerType2[i];
6462       locDa->incrRef();
6463       idsInPflPerType[i]=locDa;
6464     }
6465   std::size_t sz=idsPerType2.size();
6466   idsPerType.resize(sz);
6467   for(std::size_t i=0;i<sz;i++)
6468     {
6469       DataArrayInt *locDa=idsPerType2[i];
6470       locDa->incrRef();
6471       idsPerType[i]=locDa;
6472     }
6473 }
6474
6475 /*!
6476  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6477  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6478  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6479  * 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.
6480  */
6481 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6482 {
6483   checkFullyDefined();
6484   nM1LevMesh->checkFullyDefined();
6485   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6486     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6487   if(_coords!=nM1LevMesh->getCoords())
6488     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6489   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6491   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6492   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6493   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6494   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6495   tmp->setConnectivity(tmp0,tmp1);
6496   tmp->renumberCells(ret0->getConstPointer(),false);
6497   revDesc=tmp->getNodalConnectivity();
6498   revDescIndx=tmp->getNodalConnectivityIndex();
6499   DataArrayInt *ret=0;
6500   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6501     {
6502       int tmp2;
6503       ret->getMaxValue(tmp2);
6504       ret->decrRef();
6505       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6506       throw INTERP_KERNEL::Exception(oss.str().c_str());
6507     }
6508   nM1LevMeshIds=ret;
6509   //
6510   revDesc->incrRef();
6511   revDescIndx->incrRef();
6512   ret1->incrRef();
6513   ret0->incrRef();
6514   meshnM1Old2New=ret0;
6515   return ret1;
6516 }
6517
6518 /*!
6519  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6520  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6521  * in "Old to New" mode.
6522  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6523  *          this array using decrRef() as it is no more needed.
6524  *  \throw If the nodal connectivity of cells is not defined.
6525  */
6526 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6527 {
6528   checkConnectivityFullyDefined();
6529   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6530   renumberCells(ret->getConstPointer(),false);
6531   return ret.retn();
6532 }
6533
6534 /*!
6535  * This methods checks that cells are sorted by their types.
6536  * This method makes asumption (no check) that connectivity is correctly set before calling.
6537  */
6538 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6539 {
6540   checkFullyDefined();
6541   const int *conn=_nodal_connec->getConstPointer();
6542   const int *connI=_nodal_connec_index->getConstPointer();
6543   int nbOfCells=getNumberOfCells();
6544   std::set<INTERP_KERNEL::NormalizedCellType> types;
6545   for(const int *i=connI;i!=connI+nbOfCells;)
6546     {
6547       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6548       if(types.find(curType)!=types.end())
6549         return false;
6550       types.insert(curType);
6551       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6552     }
6553   return true;
6554 }
6555
6556 /*!
6557  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6558  * The geometric type order is specified by MED file.
6559  * 
6560  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6561  */
6562 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6563 {
6564   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6565 }
6566
6567 /*!
6568  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6569  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6570  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6571  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6572  */
6573 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6574 {
6575   checkFullyDefined();
6576   const int *conn=_nodal_connec->getConstPointer();
6577   const int *connI=_nodal_connec_index->getConstPointer();
6578   int nbOfCells=getNumberOfCells();
6579   if(nbOfCells==0)
6580     return true;
6581   int lastPos=-1;
6582   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6583   for(const int *i=connI;i!=connI+nbOfCells;)
6584     {
6585       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6586       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6587       if(isTypeExists!=orderEnd)
6588         {
6589           int pos=(int)std::distance(orderBg,isTypeExists);
6590           if(pos<=lastPos)
6591             return false;
6592           lastPos=pos;
6593           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6594         }
6595       else
6596         {
6597           if(sg.find(curType)==sg.end())
6598             {
6599               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6600               sg.insert(curType);
6601             }
6602           else
6603             return false;
6604         }
6605     }
6606   return true;
6607 }
6608
6609 /*!
6610  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6611  * 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
6612  * 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'.
6613  */
6614 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6615 {
6616   checkConnectivityFullyDefined();
6617   int nbOfCells=getNumberOfCells();
6618   const int *conn=_nodal_connec->getConstPointer();
6619   const int *connI=_nodal_connec_index->getConstPointer();
6620   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6621   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6622   tmpa->alloc(nbOfCells,1);
6623   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6624   tmpb->fillWithZero();
6625   int *tmp=tmpa->getPointer();
6626   int *tmp2=tmpb->getPointer();
6627   for(const int *i=connI;i!=connI+nbOfCells;i++)
6628     {
6629       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6630       if(where!=orderEnd)
6631         {
6632           int pos=(int)std::distance(orderBg,where);
6633           tmp2[pos]++;
6634           tmp[std::distance(connI,i)]=pos;
6635         }
6636       else
6637         {
6638           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6639           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6640           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6641           throw INTERP_KERNEL::Exception(oss.str().c_str());
6642         }
6643     }
6644   nbPerType=tmpb.retn();
6645   return tmpa.retn();
6646 }
6647
6648 /*!
6649  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6650  *
6651  * \return a new object containing the old to new correspondance.
6652  *
6653  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6654  */
6655 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6656 {
6657   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6658 }
6659
6660 /*!
6661  * 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.
6662  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6663  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6664  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6665  */
6666 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6667 {
6668   DataArrayInt *nbPerType=0;
6669   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6670   nbPerType->decrRef();
6671   return tmpa->buildPermArrPerLevel();
6672 }
6673
6674 /*!
6675  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6676  * The number of cells remains unchanged after the call of this method.
6677  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6678  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6679  *
6680  * \return the array giving the correspondance old to new.
6681  */
6682 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6683 {
6684   checkFullyDefined();
6685   computeTypes();
6686   const int *conn=_nodal_connec->getConstPointer();
6687   const int *connI=_nodal_connec_index->getConstPointer();
6688   int nbOfCells=getNumberOfCells();
6689   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6690   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6691     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6692       {
6693         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6694         types.push_back(curType);
6695         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6696       }
6697   DataArrayInt *ret=DataArrayInt::New();
6698   ret->alloc(nbOfCells,1);
6699   int *retPtr=ret->getPointer();
6700   std::fill(retPtr,retPtr+nbOfCells,-1);
6701   int newCellId=0;
6702   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6703     {
6704       for(const int *i=connI;i!=connI+nbOfCells;i++)
6705         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6706           retPtr[std::distance(connI,i)]=newCellId++;
6707     }
6708   renumberCells(retPtr,false);
6709   return ret;
6710 }
6711
6712 /*!
6713  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6714  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6715  * This method makes asumption that connectivity is correctly set before calling.
6716  */
6717 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6718 {
6719   checkConnectivityFullyDefined();
6720   const int *conn=_nodal_connec->getConstPointer();
6721   const int *connI=_nodal_connec_index->getConstPointer();
6722   int nbOfCells=getNumberOfCells();
6723   std::vector<MEDCouplingUMesh *> ret;
6724   for(const int *i=connI;i!=connI+nbOfCells;)
6725     {
6726       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6727       int beginCellId=(int)std::distance(connI,i);
6728       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6729       int endCellId=(int)std::distance(connI,i);
6730       int sz=endCellId-beginCellId;
6731       int *cells=new int[sz];
6732       for(int j=0;j<sz;j++)
6733         cells[j]=beginCellId+j;
6734       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6735       delete [] cells;
6736       ret.push_back(m);
6737     }
6738   return ret;
6739 }
6740
6741 /*!
6742  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6743  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6744  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6745  *
6746  * \return a newly allocated instance, that the caller must manage.
6747  * \throw If \a this contains more than one geometric type.
6748  * \throw If the nodal connectivity of \a this is not fully defined.
6749  * \throw If the internal data is not coherent.
6750  */
6751 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6752 {
6753   checkConnectivityFullyDefined();
6754     if(_types.size()!=1)
6755     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6756   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6757   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6758   ret->setCoords(getCoords());
6759   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6760   if(retC)
6761     {
6762       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6763       retC->setNodalConnectivity(c);
6764     }
6765   else
6766     {
6767       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6768       if(!retD)
6769         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6770       DataArrayInt *c=0,*ci=0;
6771       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6772       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6773       retD->setNodalConnectivity(cs,cis);
6774     }
6775   return ret.retn();
6776 }
6777
6778 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6779 {
6780   checkConnectivityFullyDefined();
6781     if(_types.size()!=1)
6782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6783   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6784   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6785   if(cm.isDynamic())
6786     {
6787       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6788       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6789       throw INTERP_KERNEL::Exception(oss.str().c_str());
6790     }
6791   int nbCells=getNumberOfCells();
6792   int typi=(int)typ;
6793   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6794   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6795   int *outPtr=connOut->getPointer();
6796   const int *conn=_nodal_connec->begin();
6797   const int *connI=_nodal_connec_index->begin();
6798   nbNodesPerCell++;
6799   for(int i=0;i<nbCells;i++,connI++)
6800     {
6801       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6802         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6803       else
6804         {
6805           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 << ") !";
6806           throw INTERP_KERNEL::Exception(oss.str().c_str());
6807         }
6808     }
6809   return connOut.retn();
6810 }
6811
6812 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6813 {
6814   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6815   checkConnectivityFullyDefined();
6816   if(_types.size()!=1)
6817     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6818   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6819   if(lgth<nbCells)
6820     throw INTERP_KERNEL::Exception(msg0);
6821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6822   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6823   int *cp(c->getPointer()),*cip(ci->getPointer());
6824   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6825   cip[0]=0;
6826   for(int i=0;i<nbCells;i++,cip++,incip++)
6827     {
6828       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6829       int delta(stop-strt);
6830       if(delta>=1)
6831         {
6832           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6833             cp=std::copy(incp+strt,incp+stop,cp);
6834           else
6835             throw INTERP_KERNEL::Exception(msg0);
6836         }
6837       else
6838         throw INTERP_KERNEL::Exception(msg0);
6839       cip[1]=cip[0]+delta;
6840     }
6841   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6842 }
6843
6844 /*!
6845  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6846  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6847  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6848  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6849  * are not used here to avoid the build of big permutation array.
6850  *
6851  * \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
6852  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6853  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6854  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6855  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6856  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6857  * \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
6858  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6859  */
6860 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6861                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6862                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6863 {
6864   std::vector<const MEDCouplingUMesh *> ms2;
6865   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6866     if(*it)
6867       {
6868         (*it)->checkConnectivityFullyDefined();
6869         ms2.push_back(*it);
6870       }
6871   if(ms2.empty())
6872     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6873   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6874   int meshDim=ms2[0]->getMeshDimension();
6875   std::vector<const MEDCouplingUMesh *> m1ssm;
6876   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6877   //
6878   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6879   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6880   int fake=0,rk=0;
6881   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6882   ret1->alloc(0,1); ret2->alloc(0,1);
6883   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6884     {
6885       if(meshDim!=(*it)->getMeshDimension())
6886         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6887       if(refCoo!=(*it)->getCoords())
6888         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6889       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6890       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6891       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6892       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6893         {
6894           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6895           m1ssmSingleAuto.push_back(singleCell);
6896           m1ssmSingle.push_back(singleCell);
6897           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6898         }
6899     }
6900   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6901   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6902   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6903   for(std::size_t i=0;i<m1ssm.size();i++)
6904     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6905   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6906   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6907   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6908   return ret0.retn();
6909 }
6910
6911 /*!
6912  * This method returns a newly created DataArrayInt instance.
6913  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6914  */
6915 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6916 {
6917   checkFullyDefined();
6918   const int *conn=_nodal_connec->getConstPointer();
6919   const int *connIndex=_nodal_connec_index->getConstPointer();
6920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6921   for(const int *w=begin;w!=end;w++)
6922     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6923       ret->pushBackSilent(*w);
6924   return ret.retn();
6925 }
6926
6927 /*!
6928  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6929  * are in [0:getNumberOfCells())
6930  */
6931 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6932 {
6933   checkFullyDefined();
6934   const int *conn=_nodal_connec->getConstPointer();
6935   const int *connI=_nodal_connec_index->getConstPointer();
6936   int nbOfCells=getNumberOfCells();
6937   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6938   int *tmp=new int[nbOfCells];
6939   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6940     {
6941       int j=0;
6942       for(const int *i=connI;i!=connI+nbOfCells;i++)
6943         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6944           tmp[std::distance(connI,i)]=j++;
6945     }
6946   DataArrayInt *ret=DataArrayInt::New();
6947   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6948   ret->copyStringInfoFrom(*da);
6949   int *retPtr=ret->getPointer();
6950   const int *daPtr=da->getConstPointer();
6951   int nbOfElems=da->getNbOfElems();
6952   for(int k=0;k<nbOfElems;k++)
6953     retPtr[k]=tmp[daPtr[k]];
6954   delete [] tmp;
6955   return ret;
6956 }
6957
6958 /*!
6959  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6960  * This method \b works \b for mesh sorted by type.
6961  * cells whose ids is in 'idsPerGeoType' array.
6962  * This method conserves coords and name of mesh.
6963  */
6964 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6965 {
6966   std::vector<int> code=getDistributionOfTypes();
6967   std::size_t nOfTypesInThis=code.size()/3;
6968   int sz=0,szOfType=0;
6969   for(std::size_t i=0;i<nOfTypesInThis;i++)
6970     {
6971       if(code[3*i]!=type)
6972         sz+=code[3*i+1];
6973       else
6974         szOfType=code[3*i+1];
6975     }
6976   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6977     if(*work<0 || *work>=szOfType)
6978       {
6979         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6980         oss << ". It should be in [0," << szOfType << ") !";
6981         throw INTERP_KERNEL::Exception(oss.str().c_str());
6982       }
6983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6984   int *idsPtr=idsTokeep->getPointer();
6985   int offset=0;
6986   for(std::size_t i=0;i<nOfTypesInThis;i++)
6987     {
6988       if(code[3*i]!=type)
6989         for(int j=0;j<code[3*i+1];j++)
6990           *idsPtr++=offset+j;
6991       else
6992         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6993       offset+=code[3*i+1];
6994     }
6995   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6996   ret->copyTinyInfoFrom(this);
6997   return ret.retn();
6998 }
6999
7000 /*!
7001  * This method returns a vector of size 'this->getNumberOfCells()'.
7002  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7003  */
7004 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7005 {
7006   int ncell=getNumberOfCells();
7007   std::vector<bool> ret(ncell);
7008   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7009   const int *c=getNodalConnectivity()->getConstPointer();
7010   for(int i=0;i<ncell;i++)
7011     {
7012       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7013       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7014       ret[i]=cm.isQuadratic();
7015     }
7016   return ret;
7017 }
7018
7019 /*!
7020  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7021  */
7022 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7023 {
7024   if(other->getType()!=UNSTRUCTURED)
7025     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7026   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7027   return MergeUMeshes(this,otherC);
7028 }
7029
7030 /*!
7031  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7032  * computed by averaging coordinates of cell nodes, so this method is not a right
7033  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7034  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7035  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7036  *          components. The caller is to delete this array using decrRef() as it is
7037  *          no more needed.
7038  *  \throw If the coordinates array is not set.
7039  *  \throw If the nodal connectivity of cells is not defined.
7040  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7041  */
7042 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7043 {
7044   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7045   int spaceDim=getSpaceDimension();
7046   int nbOfCells=getNumberOfCells();
7047   ret->alloc(nbOfCells,spaceDim);
7048   ret->copyStringInfoFrom(*getCoords());
7049   double *ptToFill=ret->getPointer();
7050   const int *nodal=_nodal_connec->getConstPointer();
7051   const int *nodalI=_nodal_connec_index->getConstPointer();
7052   const double *coor=_coords->getConstPointer();
7053   for(int i=0;i<nbOfCells;i++)
7054     {
7055       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7056       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7057       ptToFill+=spaceDim;
7058     }
7059   return ret.retn();
7060 }
7061
7062 /*!
7063  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7064  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7065  * 
7066  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7067  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7068  * 
7069  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7070  * \throw If \a this is not fully defined (coordinates and connectivity)
7071  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7072  */
7073 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7074 {
7075   checkFullyDefined();
7076   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7077   int spaceDim=getSpaceDimension();
7078   int nbOfCells=getNumberOfCells();
7079   int nbOfNodes=getNumberOfNodes();
7080   ret->alloc(nbOfCells,spaceDim);
7081   double *ptToFill=ret->getPointer();
7082   const int *nodal=_nodal_connec->getConstPointer();
7083   const int *nodalI=_nodal_connec_index->getConstPointer();
7084   const double *coor=_coords->getConstPointer();
7085   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7086     {
7087       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7088       std::fill(ptToFill,ptToFill+spaceDim,0.);
7089       if(type!=INTERP_KERNEL::NORM_POLYHED)
7090         {
7091           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7092             {
7093               if(*conn>=0 && *conn<nbOfNodes)
7094                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7095               else
7096                 {
7097                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7098                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7099                 }
7100             }
7101           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7102           if(nbOfNodesInCell>0)
7103             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7104           else
7105             {
7106               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7107               throw INTERP_KERNEL::Exception(oss.str().c_str());
7108             }
7109         }
7110       else
7111         {
7112           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7113           s.erase(-1);
7114           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7115             {
7116               if(*it>=0 && *it<nbOfNodes)
7117                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7118               else
7119                 {
7120                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7121                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7122                 }
7123             }
7124           if(!s.empty())
7125             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7126           else
7127             {
7128               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7129               throw INTERP_KERNEL::Exception(oss.str().c_str());
7130             }
7131         }
7132     }
7133   return ret.retn();
7134 }
7135
7136 /*!
7137  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7138  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7139  * are specified via an array of cell ids. 
7140  *  \warning Validity of the specified cell ids is not checked! 
7141  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7142  *  \param [in] begin - an array of cell ids of interest.
7143  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7144  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7145  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7146  *          caller is to delete this array using decrRef() as it is no more needed. 
7147  *  \throw If the coordinates array is not set.
7148  *  \throw If the nodal connectivity of cells is not defined.
7149  *
7150  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7151  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7152  */
7153 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7154 {
7155   DataArrayDouble *ret=DataArrayDouble::New();
7156   int spaceDim=getSpaceDimension();
7157   int nbOfTuple=(int)std::distance(begin,end);
7158   ret->alloc(nbOfTuple,spaceDim);
7159   double *ptToFill=ret->getPointer();
7160   double *tmp=new double[spaceDim];
7161   const int *nodal=_nodal_connec->getConstPointer();
7162   const int *nodalI=_nodal_connec_index->getConstPointer();
7163   const double *coor=_coords->getConstPointer();
7164   for(const int *w=begin;w!=end;w++)
7165     {
7166       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7167       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7168       ptToFill+=spaceDim;
7169     }
7170   delete [] tmp;
7171   return ret;
7172 }
7173
7174 /*!
7175  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7176  * 
7177  */
7178 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7179 {
7180   if(!da)
7181     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7182   da->checkAllocated();
7183   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7184   ret->setCoords(da);
7185   int nbOfTuples=da->getNumberOfTuples();
7186   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7187   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7188   c->alloc(2*nbOfTuples,1);
7189   cI->alloc(nbOfTuples+1,1);
7190   int *cp=c->getPointer();
7191   int *cip=cI->getPointer();
7192   *cip++=0;
7193   for(int i=0;i<nbOfTuples;i++)
7194     {
7195       *cp++=INTERP_KERNEL::NORM_POINT1;
7196       *cp++=i;
7197       *cip++=2*(i+1);
7198     }
7199   ret->setConnectivity(c,cI,true);
7200   return ret.retn();
7201 }
7202 /*!
7203  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7204  * Cells and nodes of
7205  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7206  *  \param [in] mesh1 - the first mesh.
7207  *  \param [in] mesh2 - the second mesh.
7208  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7209  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7210  *          is no more needed.
7211  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7212  *  \throw If the coordinates array is not set in none of the meshes.
7213  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7214  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7215  */
7216 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7217 {
7218   std::vector<const MEDCouplingUMesh *> tmp(2);
7219   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7220   return MergeUMeshes(tmp);
7221 }
7222
7223 /*!
7224  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7225  * Cells and nodes of
7226  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7227  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7228  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7229  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7230  *          is no more needed.
7231  *  \throw If \a a.size() == 0.
7232  *  \throw If \a a[ *i* ] == NULL.
7233  *  \throw If the coordinates array is not set in none of the meshes.
7234  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7235  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7236 */
7237 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7238 {
7239   std::size_t sz=a.size();
7240   if(sz==0)
7241     return MergeUMeshesLL(a);
7242   for(std::size_t ii=0;ii<sz;ii++)
7243     if(!a[ii])
7244       {
7245         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7246         throw INTERP_KERNEL::Exception(oss.str().c_str());
7247       }
7248   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7249   std::vector< const MEDCouplingUMesh * > aa(sz);
7250   int spaceDim=-3;
7251   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7252     {
7253       const MEDCouplingUMesh *cur=a[i];
7254       const DataArrayDouble *coo=cur->getCoords();
7255       if(coo)
7256         spaceDim=coo->getNumberOfComponents();
7257     }
7258   if(spaceDim==-3)
7259     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7260   for(std::size_t i=0;i<sz;i++)
7261     {
7262       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7263       aa[i]=bb[i];
7264     }
7265   return MergeUMeshesLL(aa);
7266 }
7267
7268 /// @cond INTERNAL
7269
7270 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7271 {
7272   if(a.empty())
7273     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7274   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7275   int meshDim=(*it)->getMeshDimension();
7276   int nbOfCells=(*it)->getNumberOfCells();
7277   int meshLgth=(*it++)->getMeshLength();
7278   for(;it!=a.end();it++)
7279     {
7280       if(meshDim!=(*it)->getMeshDimension())
7281         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7282       nbOfCells+=(*it)->getNumberOfCells();
7283       meshLgth+=(*it)->getMeshLength();
7284     }
7285   std::vector<const MEDCouplingPointSet *> aps(a.size());
7286   std::copy(a.begin(),a.end(),aps.begin());
7287   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7288   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7289   ret->setCoords(pts);
7290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7291   c->alloc(meshLgth,1);
7292   int *cPtr=c->getPointer();
7293   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7294   cI->alloc(nbOfCells+1,1);
7295   int *cIPtr=cI->getPointer();
7296   *cIPtr++=0;
7297   int offset=0;
7298   int offset2=0;
7299   for(it=a.begin();it!=a.end();it++)
7300     {
7301       int curNbOfCell=(*it)->getNumberOfCells();
7302       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7303       const int *curC=(*it)->_nodal_connec->getConstPointer();
7304       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7305       for(int j=0;j<curNbOfCell;j++)
7306         {
7307           const int *src=curC+curCI[j];
7308           *cPtr++=*src++;
7309           for(;src!=curC+curCI[j+1];src++,cPtr++)
7310             {
7311               if(*src!=-1)
7312                 *cPtr=*src+offset2;
7313               else
7314                 *cPtr=-1;
7315             }
7316         }
7317       offset+=curCI[curNbOfCell];
7318       offset2+=(*it)->getNumberOfNodes();
7319     }
7320   //
7321   ret->setConnectivity(c,cI,true);
7322   return ret.retn();
7323 }
7324
7325 /// @endcond
7326
7327 /*!
7328  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7329  * dimension and sharing the node coordinates array.
7330  * All cells of the first mesh precede all cells of the second mesh
7331  * within the result mesh. 
7332  *  \param [in] mesh1 - the first mesh.
7333  *  \param [in] mesh2 - the second mesh.
7334  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7335  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7336  *          is no more needed.
7337  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7338  *  \throw If the meshes do not share the node coordinates array.
7339  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7340  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7341  */
7342 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7343 {
7344   std::vector<const MEDCouplingUMesh *> tmp(2);
7345   tmp[0]=mesh1; tmp[1]=mesh2;
7346   return MergeUMeshesOnSameCoords(tmp);
7347 }
7348
7349 /*!
7350  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7351  * dimension and sharing the node coordinates array.
7352  * All cells of the *i*-th mesh precede all cells of the
7353  * (*i*+1)-th mesh within the result mesh.
7354  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7355  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7356  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7357  *          is no more needed.
7358  *  \throw If \a a.size() == 0.
7359  *  \throw If \a a[ *i* ] == NULL.
7360  *  \throw If the meshes do not share the node coordinates array.
7361  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7362  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7363  */
7364 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7365 {
7366   if(meshes.empty())
7367     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7368   for(std::size_t ii=0;ii<meshes.size();ii++)
7369     if(!meshes[ii])
7370       {
7371         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7372         throw INTERP_KERNEL::Exception(oss.str().c_str());
7373       }
7374   const DataArrayDouble *coords=meshes.front()->getCoords();
7375   int meshDim=meshes.front()->getMeshDimension();
7376   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7377   int meshLgth=0;
7378   int meshIndexLgth=0;
7379   for(;iter!=meshes.end();iter++)
7380     {
7381       if(coords!=(*iter)->getCoords())
7382         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7383       if(meshDim!=(*iter)->getMeshDimension())
7384         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7385       meshLgth+=(*iter)->getMeshLength();
7386       meshIndexLgth+=(*iter)->getNumberOfCells();
7387     }
7388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7389   nodal->alloc(meshLgth,1);
7390   int *nodalPtr=nodal->getPointer();
7391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7392   nodalIndex->alloc(meshIndexLgth+1,1);
7393   int *nodalIndexPtr=nodalIndex->getPointer();
7394   int offset=0;
7395   for(iter=meshes.begin();iter!=meshes.end();iter++)
7396     {
7397       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7398       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7399       int nbOfCells=(*iter)->getNumberOfCells();
7400       int meshLgth2=(*iter)->getMeshLength();
7401       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7402       if(iter!=meshes.begin())
7403         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7404       else
7405         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7406       offset+=meshLgth2;
7407     }
7408   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7409   ret->setName("merge");
7410   ret->setMeshDimension(meshDim);
7411   ret->setConnectivity(nodal,nodalIndex,true);
7412   ret->setCoords(coords);
7413   return ret;
7414 }
7415
7416 /*!
7417  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7418  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7419  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7420  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7421  * New" mode are returned for each input mesh.
7422  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7423  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7424  *          valid values [0,1,2], see zipConnectivityTraducer().
7425  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7426  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7427  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7428  *          no more needed.
7429  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7430  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7431  *          is no more needed.
7432  *  \throw If \a meshes.size() == 0.
7433  *  \throw If \a meshes[ *i* ] == NULL.
7434  *  \throw If the meshes do not share the node coordinates array.
7435  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7436  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7437  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7438  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7439  */
7440 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7441 {
7442   //All checks are delegated to MergeUMeshesOnSameCoords
7443   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7444   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7445   corr.resize(meshes.size());
7446   std::size_t nbOfMeshes=meshes.size();
7447   int offset=0;
7448   const int *o2nPtr=o2n->getConstPointer();
7449   for(std::size_t i=0;i<nbOfMeshes;i++)
7450     {
7451       DataArrayInt *tmp=DataArrayInt::New();
7452       int curNbOfCells=meshes[i]->getNumberOfCells();
7453       tmp->alloc(curNbOfCells,1);
7454       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7455       offset+=curNbOfCells;
7456       tmp->setName(meshes[i]->getName().c_str());
7457       corr[i]=tmp;
7458     }
7459   return ret.retn();
7460 }
7461
7462 /*!
7463  * Makes all given meshes share the nodal connectivity array. The common connectivity
7464  * array is created by concatenating the connectivity arrays of all given meshes. All
7465  * the given meshes must be of the same space dimension but dimension of cells **can
7466  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7467  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7468  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7469  *  \param [in,out] meshes - a vector of meshes to update.
7470  *  \throw If any of \a meshes is NULL.
7471  *  \throw If the coordinates array is not set in any of \a meshes.
7472  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7473  *  \throw If \a meshes are of different space dimension.
7474  */
7475 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7476 {
7477   std::size_t sz=meshes.size();
7478   if(sz==0 || sz==1)
7479     return;
7480   std::vector< const DataArrayDouble * > coords(meshes.size());
7481   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7482   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7483     {
7484       if((*it))
7485         {
7486           (*it)->checkConnectivityFullyDefined();
7487           const DataArrayDouble *coo=(*it)->getCoords();
7488           if(coo)
7489             *it2=coo;
7490           else
7491             {
7492               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7493               oss << " has no coordinate array defined !";
7494               throw INTERP_KERNEL::Exception(oss.str().c_str());
7495             }
7496         }
7497       else
7498         {
7499           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7500           oss << " is null !";
7501           throw INTERP_KERNEL::Exception(oss.str().c_str());
7502         }
7503     }
7504   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7505   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7506   int offset=(*it)->getNumberOfNodes();
7507   (*it++)->setCoords(res);
7508   for(;it!=meshes.end();it++)
7509     {
7510       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7511       (*it)->setCoords(res);
7512       (*it)->shiftNodeNumbersInConn(offset);
7513       offset+=oldNumberOfNodes;
7514     }
7515 }
7516
7517 /*!
7518  * Merges nodes coincident with a given precision within all given meshes that share
7519  * the nodal connectivity array. The given meshes **can be of different** mesh
7520  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7521  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7522  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7523  *  \param [in,out] meshes - a vector of meshes to update.
7524  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7525  *  \throw If any of \a meshes is NULL.
7526  *  \throw If the \a meshes do not share the same node coordinates array.
7527  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7528  */
7529 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7530 {
7531   if(meshes.empty())
7532     return ;
7533   std::set<const DataArrayDouble *> s;
7534   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7535     {
7536       if(*it)
7537         s.insert((*it)->getCoords());
7538       else
7539         {
7540           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 !";
7541           throw INTERP_KERNEL::Exception(oss.str().c_str());
7542         }
7543     }
7544   if(s.size()!=1)
7545     {
7546       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 !";
7547       throw INTERP_KERNEL::Exception(oss.str().c_str());
7548     }
7549   const DataArrayDouble *coo=*(s.begin());
7550   if(!coo)
7551     return;
7552   //
7553   DataArrayInt *comm,*commI;
7554   coo->findCommonTuples(eps,-1,comm,commI);
7555   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7556   int oldNbOfNodes=coo->getNumberOfTuples();
7557   int newNbOfNodes;
7558   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7559   if(oldNbOfNodes==newNbOfNodes)
7560     return ;
7561   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7562   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7563     {
7564       (*it)->renumberNodesInConn(o2n->getConstPointer());
7565       (*it)->setCoords(newCoords);
7566     } 
7567 }
7568
7569 /*!
7570  * 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.
7571  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7572  * \param isQuad specifies the policy of connectivity.
7573  * @ret in/out parameter in which the result will be append
7574  */
7575 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7576 {
7577   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7578   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7579   ret.push_back(cm.getExtrudedType());
7580   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7581   switch(flatType)
7582     {
7583     case INTERP_KERNEL::NORM_POINT1:
7584       {
7585         ret.push_back(connBg[1]);
7586         ret.push_back(connBg[1]+nbOfNodesPerLev);
7587         break;
7588       }
7589     case INTERP_KERNEL::NORM_SEG2:
7590       {
7591         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7592         ret.insert(ret.end(),conn,conn+4);
7593         break;
7594       }
7595     case INTERP_KERNEL::NORM_SEG3:
7596       {
7597         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7598         ret.insert(ret.end(),conn,conn+8);
7599         break;
7600       }
7601     case INTERP_KERNEL::NORM_QUAD4:
7602       {
7603         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7604         ret.insert(ret.end(),conn,conn+8);
7605         break;
7606       }
7607     case INTERP_KERNEL::NORM_TRI3:
7608       {
7609         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7610         ret.insert(ret.end(),conn,conn+6);
7611         break;
7612       }
7613     case INTERP_KERNEL::NORM_TRI6:
7614       {
7615         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,
7616                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7617         ret.insert(ret.end(),conn,conn+15);
7618         break;
7619       }
7620     case INTERP_KERNEL::NORM_QUAD8:
7621       {
7622         int conn[20]={
7623           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7624           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7625           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7626         };
7627         ret.insert(ret.end(),conn,conn+20);
7628         break;
7629       }
7630     case INTERP_KERNEL::NORM_POLYGON:
7631       {
7632         std::back_insert_iterator< std::vector<int> > ii(ret);
7633         std::copy(connBg+1,connEnd,ii);
7634         *ii++=-1;
7635         std::reverse_iterator<const int *> rConnBg(connEnd);
7636         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7637         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7638         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7639         for(std::size_t i=0;i<nbOfRadFaces;i++)
7640           {
7641             *ii++=-1;
7642             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7643             std::copy(conn,conn+4,ii);
7644           }
7645         break;
7646       }
7647     default:
7648       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7649     }
7650 }
7651
7652 /*!
7653  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7654  */
7655 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7656 {
7657   double v[3]={0.,0.,0.};
7658   std::size_t sz=std::distance(begin,end);
7659   if(isQuadratic)
7660     sz/=2;
7661   for(std::size_t i=0;i<sz;i++)
7662     {
7663       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];
7664       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7665       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7666     }
7667   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7668 }
7669
7670 /*!
7671  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7672  */
7673 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7674 {
7675   std::vector<std::pair<int,int> > edges;
7676   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7677   const int *bgFace=begin;
7678   for(std::size_t i=0;i<nbOfFaces;i++)
7679     {
7680       const int *endFace=std::find(bgFace+1,end,-1);
7681       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7682       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7683         {
7684           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7685           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7686             return false;
7687           edges.push_back(p1);
7688         }
7689       bgFace=endFace+1;
7690     }
7691   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7692 }
7693
7694 /*!
7695  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7696  */
7697 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7698 {
7699   double vec0[3],vec1[3];
7700   std::size_t sz=std::distance(begin,end);
7701   if(sz%2!=0)
7702     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7703   int nbOfNodes=(int)sz/2;
7704   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7705   const double *pt0=coords+3*begin[0];
7706   const double *pt1=coords+3*begin[nbOfNodes];
7707   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7708   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7709 }
7710
7711 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7712 {
7713   std::size_t sz=std::distance(begin,end);
7714   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7715   std::size_t nbOfNodes(sz/2);
7716   std::copy(begin,end,(int *)tmp);
7717   for(std::size_t j=1;j<nbOfNodes;j++)
7718     {
7719       begin[j]=tmp[nbOfNodes-j];
7720       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7721     }
7722 }
7723
7724 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7725 {
7726   std::size_t sz=std::distance(begin,end);
7727   if(sz!=4)
7728     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7729   double vec0[3],vec1[3];
7730   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7731   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]; 
7732   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;
7733 }
7734
7735 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7736 {
7737   std::size_t sz=std::distance(begin,end);
7738   if(sz!=5)
7739     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7740   double vec0[3];
7741   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7742   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7743   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7744 }
7745
7746 /*!
7747  * 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 ) 
7748  * 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
7749  * a 2D space.
7750  *
7751  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7752  * \param [in] coords the coordinates with nb of components exactly equal to 3
7753  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7754  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7755  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7756  */
7757 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7758 {
7759   int nbFaces=std::count(begin+1,end,-1)+1;
7760   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7761   double *vPtr=v->getPointer();
7762   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7763   double *pPtr=p->getPointer();
7764   const int *stFaceConn=begin+1;
7765   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7766     {
7767       const int *endFaceConn=std::find(stFaceConn,end,-1);
7768       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7769       stFaceConn=endFaceConn+1;
7770     }
7771   pPtr=p->getPointer(); vPtr=v->getPointer();
7772   DataArrayInt *comm1=0,*commI1=0;
7773   v->findCommonTuples(eps,-1,comm1,commI1);
7774   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7775   const int *comm1Ptr=comm1->getConstPointer();
7776   const int *commI1Ptr=commI1->getConstPointer();
7777   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7778   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7779   //
7780   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7781   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7782   mm->finishInsertingCells();
7783   //
7784   for(int i=0;i<nbOfGrps1;i++)
7785     {
7786       int vecId=comm1Ptr[commI1Ptr[i]];
7787       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7788       DataArrayInt *comm2=0,*commI2=0;
7789       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7790       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7791       const int *comm2Ptr=comm2->getConstPointer();
7792       const int *commI2Ptr=commI2->getConstPointer();
7793       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7794       for(int j=0;j<nbOfGrps2;j++)
7795         {
7796           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7797             {
7798               res->insertAtTheEnd(begin,end);
7799               res->pushBackSilent(-1);
7800             }
7801           else
7802             {
7803               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7804               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7805               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7806               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7807               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7808               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7809               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7810               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7811               const int *idsNodePtr=idsNode->getConstPointer();
7812               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];
7813               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7814               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7815               if(std::abs(norm)>eps)
7816                 {
7817                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7818                   mm3->rotate(center,vec,angle);
7819                 }
7820               mm3->changeSpaceDimension(2);
7821               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7822               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7823               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7824               int nbOfCells=mm4->getNumberOfCells();
7825               for(int k=0;k<nbOfCells;k++)
7826                 {
7827                   int l=0;
7828                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7829                     res->pushBackSilent(idsNodePtr[*work]);
7830                   res->pushBackSilent(-1);
7831                 }
7832             }
7833         }
7834     }
7835   res->popBackSilent();
7836 }
7837
7838 /*!
7839  * 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
7840  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7841  * 
7842  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7843  * \param [in] coords coordinates expected to have 3 components.
7844  * \param [in] begin start of the nodal connectivity of the face.
7845  * \param [in] end end of the nodal connectivity (excluded) of the face.
7846  * \param [out] v the normalized vector of size 3
7847  * \param [out] p the pos of plane
7848  */
7849 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7850 {
7851   std::size_t nbPoints=std::distance(begin,end);
7852   if(nbPoints<3)
7853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7854   double vec[3]={0.,0.,0.};
7855   std::size_t j=0;
7856   bool refFound=false;
7857   for(;j<nbPoints-1 && !refFound;j++)
7858     {
7859       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7860       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7861       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7862       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7863       if(norm>eps)
7864         {
7865           refFound=true;
7866           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7867         }
7868     }
7869   for(std::size_t i=j;i<nbPoints-1;i++)
7870     {
7871       double curVec[3];
7872       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7873       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7874       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7875       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7876       if(norm<eps)
7877         continue;
7878       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7879       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];
7880       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7881       if(norm>eps)
7882         {
7883           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7884           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7885           return ;
7886         }
7887     }
7888   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7889 }
7890
7891 /*!
7892  * This method tries to obtain a well oriented polyhedron.
7893  * If the algorithm fails, an exception will be thrown.
7894  */
7895 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7896 {
7897   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7898   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7899   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7900   isPerm[0]=true;
7901   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7902   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7903   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7904   //
7905   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7906     {
7907       bgFace=begin;
7908       std::size_t smthChanged=0;
7909       for(std::size_t i=0;i<nbOfFaces;i++)
7910         {
7911           endFace=std::find(bgFace+1,end,-1);
7912           nbOfEdgesInFace=std::distance(bgFace,endFace);
7913           if(!isPerm[i])
7914             {
7915               bool b;
7916               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7917                 {
7918                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7919                   std::pair<int,int> p2(p1.second,p1.first);
7920                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7921                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7922                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7923                 }
7924               if(isPerm[i])
7925                 { 
7926                   if(!b)
7927                     std::reverse(bgFace+1,endFace);
7928                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7929                     {
7930                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7931                       std::pair<int,int> p2(p1.second,p1.first);
7932                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7933                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7934                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7935                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7936                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7937                       if(it!=edgesOK.end())
7938                         {
7939                           edgesOK.erase(it);
7940                           edgesFinished.push_back(p1);
7941                         }
7942                       else
7943                         edgesOK.push_back(p1);
7944                     }
7945                 }
7946             }
7947           bgFace=endFace+1;
7948         }
7949       if(smthChanged==0)
7950         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7951     }
7952   if(!edgesOK.empty())
7953     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7954   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7955     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7956       bgFace=begin;
7957       for(std::size_t i=0;i<nbOfFaces;i++)
7958         {
7959           endFace=std::find(bgFace+1,end,-1);
7960           std::reverse(bgFace+1,endFace);
7961           bgFace=endFace+1;
7962         }
7963     }
7964 }
7965
7966 /*!
7967  * This method makes the assumption spacedimension == meshdimension == 2.
7968  * This method works only for linear cells.
7969  * 
7970  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7971  */
7972 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7973 {
7974   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7975     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7976   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7978   int nbOfNodesExpected=m->getNumberOfNodes();
7979   if(m->getNumberOfCells()!=nbOfNodesExpected)
7980     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7981   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7982   const int *n2oPtr=n2o->getConstPointer();
7983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7984   m->getReverseNodalConnectivity(revNodal,revNodalI);
7985   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7986   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7987   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7989   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7990   if(nbOfNodesExpected<1)
7991     return ret.retn();
7992   int prevCell=0;
7993   int prevNode=nodalPtr[nodalIPtr[0]+1];
7994   *work++=n2oPtr[prevNode];
7995   for(int i=1;i<nbOfNodesExpected;i++)
7996     {
7997       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7998         {
7999           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8000           conn.erase(prevNode);
8001           if(conn.size()==1)
8002             {
8003               int curNode=*(conn.begin());
8004               *work++=n2oPtr[curNode];
8005               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8006               shar.erase(prevCell);
8007               if(shar.size()==1)
8008                 {
8009                   prevCell=*(shar.begin());
8010                   prevNode=curNode;
8011                 }
8012               else
8013                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8014             }
8015           else
8016             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8017         }
8018       else
8019         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8020     }
8021   return ret.retn();
8022 }
8023
8024 /*!
8025  * This method makes the assumption spacedimension == meshdimension == 3.
8026  * This method works only for linear cells.
8027  * 
8028  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8029  */
8030 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8031 {
8032   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8033     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8034   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8035   const int *conn=m->getNodalConnectivity()->getConstPointer();
8036   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8037   int nbOfCells=m->getNumberOfCells();
8038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8039   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8040   if(nbOfCells<1)
8041     return ret.retn();
8042   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8043   for(int i=1;i<nbOfCells;i++)
8044     {
8045       *work++=-1;
8046       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8047     }
8048   return ret.retn();
8049 }
8050
8051 /*!
8052  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8053  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8054  */
8055 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8056 {
8057   double *w=zipFrmt;
8058   if(spaceDim==3)
8059     for(int i=0;i<nbOfNodesInCell;i++)
8060       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8061   else if(spaceDim==2)
8062     {
8063       for(int i=0;i<nbOfNodesInCell;i++)
8064         {
8065           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8066           *w++=0.;
8067         }
8068     }
8069   else
8070     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8071 }
8072
8073 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8074 {
8075   int nbOfCells=getNumberOfCells();
8076   if(nbOfCells<=0)
8077     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8078   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};
8079   ofs << "  <" << getVTKDataSetType() << ">\n";
8080   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8081   ofs << "      <PointData>\n" << pointData << std::endl;
8082   ofs << "      </PointData>\n";
8083   ofs << "      <CellData>\n" << cellData << std::endl;
8084   ofs << "      </CellData>\n";
8085   ofs << "      <Points>\n";
8086   if(getSpaceDimension()==3)
8087     _coords->writeVTK(ofs,8,"Points");
8088   else
8089     {
8090       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8091       coo->writeVTK(ofs,8,"Points");
8092     }
8093   ofs << "      </Points>\n";
8094   ofs << "      <Cells>\n";
8095   const int *cPtr=_nodal_connec->getConstPointer();
8096   const int *cIPtr=_nodal_connec_index->getConstPointer();
8097   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8099   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8100   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8101   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8102   int szFaceOffsets=0,szConn=0;
8103   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8104     {
8105       *w2=cPtr[cIPtr[i]];
8106       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8107         {
8108           *w1=-1;
8109           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8110           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8111         }
8112       else
8113         {
8114           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8115           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8116           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8117           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8118           w4=std::copy(c.begin(),c.end(),w4);
8119         }
8120     }
8121   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8122   types->writeVTK(ofs,8,"UInt8","types");
8123   offsets->writeVTK(ofs,8,"Int32","offsets");
8124   if(szFaceOffsets!=0)
8125     {//presence of Polyhedra
8126       connectivity->reAlloc(szConn);
8127       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8128       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8129       w1=faces->getPointer();
8130       for(int i=0;i<nbOfCells;i++)
8131         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8132           {
8133             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8134             *w1++=nbFaces;
8135             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8136             for(int j=0;j<nbFaces;j++)
8137               {
8138                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8139                 *w1++=(int)std::distance(w6,w5);
8140                 w1=std::copy(w6,w5,w1);
8141                 w6=w5+1;
8142               }
8143           }
8144       faces->writeVTK(ofs,8,"Int32","faces");
8145     }
8146   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8147   ofs << "      </Cells>\n";
8148   ofs << "    </Piece>\n";
8149   ofs << "  </" << getVTKDataSetType() << ">\n";
8150 }
8151
8152 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8153 {
8154   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8155   if(_mesh_dim==-2)
8156     { stream << " Not set !"; return ; }
8157   stream << " Mesh dimension : " << _mesh_dim << ".";
8158   if(_mesh_dim==-1)
8159     return ;
8160   if(!_coords)
8161     { stream << " No coordinates set !"; return ; }
8162   if(!_coords->isAllocated())
8163     { stream << " Coordinates set but not allocated !"; return ; }
8164   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8165   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8166   if(!_nodal_connec_index)
8167     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8168   if(!_nodal_connec_index->isAllocated())
8169     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8170   int lgth=_nodal_connec_index->getNumberOfTuples();
8171   int cpt=_nodal_connec_index->getNumberOfComponents();
8172   if(cpt!=1 || lgth<1)
8173     return ;
8174   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8175 }
8176
8177 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8178 {
8179   return std::string("UnstructuredGrid");
8180 }
8181
8182 /*!
8183  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8184  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8185  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8186  * meshes.
8187  *  \param [in] m1 - the first input mesh which is a partitioned object.
8188  *  \param [in] m2 - the second input mesh which is a partition tool.
8189  *  \param [in] eps - precision used to detect coincident mesh entities.
8190  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8191  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8192  *         this array using decrRef() as it is no more needed.
8193  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8194  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8195  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8196  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8197  *         it is no more needed.  
8198  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8199  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8200  *         is no more needed.  
8201  *  \throw If the coordinates array is not set in any of the meshes.
8202  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8203  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8204  */
8205 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8206 {
8207   m1->checkFullyDefined();
8208   m2->checkFullyDefined();
8209   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8210     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8211   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8212   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8213   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8214   std::vector<double> addCoo,addCoordsQuadratic;
8215   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8216   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8217   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8218                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8219   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8220   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8221   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8222   std::vector< std::vector<int> > intersectEdge2;
8223   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8224   subDiv2.clear(); dd5=0; dd6=0;
8225   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8226   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8227   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8228                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8229   //
8230   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8231   addCooDa->alloc((int)(addCoo.size())/2,2);
8232   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8233   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8234   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8235   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8236   std::vector<const DataArrayDouble *> coordss(4);
8237   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8238   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8239   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8240   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8244   ret->setConnectivity(conn,connI,true);
8245   ret->setCoords(coo);
8246   cellNb1=c1.retn(); cellNb2=c2.retn();
8247   return ret.retn();
8248 }
8249
8250 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8251                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8252                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8253                                                          const std::vector<double>& addCoords,
8254                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8255 {
8256   static const int SPACEDIM=2;
8257   const double *coo1=m1->getCoords()->getConstPointer();
8258   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8259   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8260   int offset1=m1->getNumberOfNodes();
8261   const double *coo2=m2->getCoords()->getConstPointer();
8262   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8263   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8264   int offset2=offset1+m2->getNumberOfNodes();
8265   int offset3=offset2+((int)addCoords.size())/2;
8266   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8267   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8268   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8269   int ncell1=m1->getNumberOfCells();
8270   crI.push_back(0);
8271   for(int i=0;i<ncell1;i++)
8272     {
8273       std::vector<int> candidates2;
8274       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8275       std::map<INTERP_KERNEL::Node *,int> mapp;
8276       std::map<int,INTERP_KERNEL::Node *> mappRev;
8277       INTERP_KERNEL::QuadraticPolygon pol1;
8278       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8279       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8280       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8281       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8282                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8283       //
8284       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
8285       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8286       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8287       for(it1.first();!it1.finished();it1.next())
8288         edges1.insert(it1.current()->getPtr());
8289       //
8290       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8291       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8292       int ii=0;
8293       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8294         {
8295           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8296           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8297           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8298           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8299                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8300         }
8301       ii=0;
8302       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8303         {
8304           pol1.initLocationsWithOther(pol2s[ii]);
8305           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8306           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8307           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8308         }
8309       if(!edges1.empty())
8310         {
8311           try
8312             {
8313               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8314             }
8315           catch(INTERP_KERNEL::Exception& e)
8316             {
8317               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();
8318               throw INTERP_KERNEL::Exception(oss.str().c_str());
8319             }
8320         }
8321       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8322         (*it).second->decrRef();
8323     }
8324 }
8325
8326 /*!
8327  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8328  * 
8329  */
8330 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8331                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8332                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8333                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8334                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8335 {
8336   static const int SPACEDIM=2;
8337   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8338   desc2=DataArrayInt::New();
8339   descIndx2=DataArrayInt::New();
8340   revDesc2=DataArrayInt::New();
8341   revDescIndx2=DataArrayInt::New();
8342   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8344   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8345   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8346   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8347   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8348   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8349   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8350   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8351   int ncell1=m1Desc->getNumberOfCells();
8352   int ncell2=m2Desc->getNumberOfCells();
8353   intersectEdge1.resize(ncell1);
8354   colinear2.resize(ncell2);
8355   subDiv2.resize(ncell2);
8356   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8357   std::vector<int> candidates1(1);
8358   int offset1=m1->getNumberOfNodes();
8359   int offset2=offset1+m2->getNumberOfNodes();
8360   for(int i=0;i<ncell1;i++)
8361     {
8362       std::vector<int> candidates2;
8363       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8364       if(!candidates2.empty())
8365         {
8366           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8367           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8368           candidates1[0]=i;
8369           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8370           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8371           delete pol2;
8372           delete pol1;
8373         }
8374       else
8375         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8376     }
8377   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8378   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8379 }
8380
8381 /*!
8382  * This method performs the 2nd step of Partition of 2D mesh.
8383  * This method has 4 inputs :
8384  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8385  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8386  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8387  * 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'
8388  * \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'
8389  * \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.
8390  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8391  */
8392 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)
8393 {
8394   int offset1=m1->getNumberOfNodes();
8395   int ncell=m2->getNumberOfCells();
8396   const int *c=m2->getNodalConnectivity()->getConstPointer();
8397   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8398   const double *coo=m2->getCoords()->getConstPointer();
8399   const double *cooBis=m1->getCoords()->getConstPointer();
8400   int offset2=offset1+m2->getNumberOfNodes();
8401   intersectEdge.resize(ncell);
8402   for(int i=0;i<ncell;i++,cI++)
8403     {
8404       const std::vector<int>& divs=subDiv[i];
8405       int nnode=cI[1]-cI[0]-1;
8406       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8407       std::map<INTERP_KERNEL::Node *, int> mapp22;
8408       for(int j=0;j<nnode;j++)
8409         {
8410           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8411           int nnid=c[(*cI)+j+1];
8412           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8413           mapp22[nn]=nnid+offset1;
8414         }
8415       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8416       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8417         ((*it).second.first)->decrRef();
8418       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8419       std::map<INTERP_KERNEL::Node *,int> mapp3;
8420       for(std::size_t j=0;j<divs.size();j++)
8421         {
8422           int id=divs[j];
8423           INTERP_KERNEL::Node *tmp=0;
8424           if(id<offset1)
8425             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8426           else if(id<offset2)
8427             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8428           else
8429             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8430           addNodes[j]=tmp;
8431           mapp3[tmp]=id;
8432         }
8433       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8434       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8435         (*it)->decrRef();
8436       e->decrRef();
8437     }
8438 }
8439
8440 /*!
8441  * 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).
8442  * 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
8443  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8444  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8445  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8446  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8447  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8448  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8449  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8450  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8451  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8452  * \param [out] cut3DSuf input/output param.
8453  */
8454 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8455                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8456                                                    const int *desc, const int *descIndx, 
8457                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8458 {
8459   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8460   int nbOf3DSurfCell=(int)cut3DSurf.size();
8461   for(int i=0;i<nbOf3DSurfCell;i++)
8462     {
8463       std::vector<int> res;
8464       int offset=descIndx[i];
8465       int nbOfSeg=descIndx[i+1]-offset;
8466       for(int j=0;j<nbOfSeg;j++)
8467         {
8468           int edgeId=desc[offset+j];
8469           int status=cut3DCurve[edgeId];
8470           if(status!=-2)
8471             {
8472               if(status>-1)
8473                 res.push_back(status);
8474               else
8475                 {
8476                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8477                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8478                 }
8479             }
8480         }
8481       switch(res.size())
8482         {
8483         case 2:
8484           {
8485             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8486             break;
8487           }
8488         case 1:
8489         case 0:
8490           {
8491             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8492             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8493             if(res.size()==2)
8494               {
8495                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8496               }
8497             else
8498               {
8499                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8500               }
8501             break;
8502           }
8503         default:
8504           {// case when plane is on a multi colinear edge of a polyhedron
8505             if((int)res.size()==2*nbOfSeg)
8506               {
8507                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8508               }
8509             else
8510               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8511           }
8512         }
8513     }
8514 }
8515
8516 /*!
8517  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8518  * 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).
8519  * 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
8520  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8521  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8522  * \param desc is the descending connectivity 3D->3DSurf
8523  * \param descIndx is the descending connectivity index 3D->3DSurf
8524  */
8525 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8526                                                   const int *desc, const int *descIndx,
8527                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8528 {
8529   checkFullyDefined();
8530   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8531     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8532   const int *nodal3D=_nodal_connec->getConstPointer();
8533   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8534   int nbOfCells=getNumberOfCells();
8535   for(int i=0;i<nbOfCells;i++)
8536     {
8537       std::map<int, std::set<int> > m;
8538       int offset=descIndx[i];
8539       int nbOfFaces=descIndx[i+1]-offset;
8540       int start=-1;
8541       int end=-1;
8542       for(int j=0;j<nbOfFaces;j++)
8543         {
8544           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8545           if(p.first!=-1 && p.second!=-1)
8546             {
8547               if(p.first!=-2)
8548                 {
8549                   start=p.first; end=p.second;
8550                   m[p.first].insert(p.second);
8551                   m[p.second].insert(p.first);
8552                 }
8553               else
8554                 {
8555                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8556                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8557                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8558                   INTERP_KERNEL::NormalizedCellType cmsId;
8559                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8560                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8561                   for(unsigned k=0;k<nbOfNodesSon;k++)
8562                     {
8563                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8564                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8565                     }
8566                 }
8567             }
8568         }
8569       if(m.empty())
8570         continue;
8571       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8572       int prev=end;
8573       while(end!=start)
8574         {
8575           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8576           const std::set<int>& s=(*it).second;
8577           std::set<int> s2; s2.insert(prev);
8578           std::set<int> s3;
8579           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8580           if(s3.size()==1)
8581             {
8582               int val=*s3.begin();
8583               conn.push_back(start);
8584               prev=start;
8585               start=val;
8586             }
8587           else
8588             start=end;
8589         }
8590       conn.push_back(end);
8591       if(conn.size()>3)
8592         {
8593           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8594           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8595           cellIds->pushBackSilent(i);
8596         }
8597     }
8598 }
8599
8600 /*!
8601  * 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
8602  * 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
8603  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8604  * 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
8605  * 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.
8606  * 
8607  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8608  */
8609 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8610 {
8611   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8612   if(sz>=4)
8613     {
8614       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8615       if(cm.getDimension()==2)
8616         {
8617           const int *node=nodalConnBg+1;
8618           int startNode=*node++;
8619           double refX=coords[2*startNode];
8620           for(;node!=nodalConnEnd;node++)
8621             {
8622               if(coords[2*(*node)]<refX)
8623                 {
8624                   startNode=*node;
8625                   refX=coords[2*startNode];
8626                 }
8627             }
8628           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8629           refX=1e300;
8630           double tmp1;
8631           double tmp2[2];
8632           double angle0=-M_PI/2;
8633           //
8634           int nextNode=-1;
8635           int prevNode=-1;
8636           double resRef;
8637           double angleNext=0.;
8638           while(nextNode!=startNode)
8639             {
8640               nextNode=-1;
8641               resRef=1e300;
8642               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8643                 {
8644                   if(*node!=tmpOut.back() && *node!=prevNode)
8645                     {
8646                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8647                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8648                       double res;
8649                       if(angleM<=angle0)
8650                         res=angle0-angleM;
8651                       else
8652                         res=angle0-angleM+2.*M_PI;
8653                       if(res<resRef)
8654                         {
8655                           nextNode=*node;
8656                           resRef=res;
8657                           angleNext=angleM;
8658                         }
8659                     }
8660                 }
8661               if(nextNode!=startNode)
8662                 {
8663                   angle0=angleNext-M_PI;
8664                   if(angle0<-M_PI)
8665                     angle0+=2*M_PI;
8666                   prevNode=tmpOut.back();
8667                   tmpOut.push_back(nextNode);
8668                 }
8669             }
8670           std::vector<int> tmp3(2*(sz-1));
8671           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8672           std::copy(nodalConnBg+1,nodalConnEnd,it);
8673           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8674             {
8675               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8676               return false;
8677             }
8678           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8679             {
8680               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8681               return false;
8682             }
8683           else
8684             {
8685               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8686               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8687               return true;
8688             }
8689         }
8690       else
8691         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8692     }
8693   else
8694     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8695 }
8696
8697 /*!
8698  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8699  * 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.
8700  * 
8701  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8702  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8703  * \param [in,out] arr array in which the remove operation will be done.
8704  * \param [in,out] arrIndx array in the remove operation will modify
8705  * \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])
8706  * \return true if \b arr and \b arrIndx have been modified, false if not.
8707  */
8708 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8709 {
8710   if(!arrIndx || !arr)
8711     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8712   if(offsetForRemoval<0)
8713     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8714   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8715   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8716   int *arrIPtr=arrIndx->getPointer();
8717   *arrIPtr++=0;
8718   int previousArrI=0;
8719   const int *arrPtr=arr->getConstPointer();
8720   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8721   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8722     {
8723       if(*arrIPtr-previousArrI>offsetForRemoval)
8724         {
8725           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8726             {
8727               if(s.find(*work)==s.end())
8728                 arrOut.push_back(*work);
8729             }
8730         }
8731       previousArrI=*arrIPtr;
8732       *arrIPtr=(int)arrOut.size();
8733     }
8734   if(arr->getNumberOfTuples()==(int)arrOut.size())
8735     return false;
8736   arr->alloc((int)arrOut.size(),1);
8737   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8738   return true;
8739 }
8740
8741 /*!
8742  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8743  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8744  * The selection of extraction is done standardly in new2old format.
8745  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8746  *
8747  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8748  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8749  * \param [in] arrIn arr origin array from which the extraction will be done.
8750  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8751  * \param [out] arrOut the resulting array
8752  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8753  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8754  */
8755 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8756                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8757 {
8758   if(!arrIn || !arrIndxIn)
8759     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8760   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8761   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8762     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8763   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8764   const int *arrInPtr=arrIn->getConstPointer();
8765   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8766   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8767   if(nbOfGrps<0)
8768     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8769   int maxSizeOfArr=arrIn->getNumberOfTuples();
8770   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8771   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8772   arrIo->alloc((int)(sz+1),1);
8773   const int *idsIt=idsOfSelectBg;
8774   int *work=arrIo->getPointer();
8775   *work++=0;
8776   int lgth=0;
8777   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8778     {
8779       if(*idsIt>=0 && *idsIt<nbOfGrps)
8780         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8781       else
8782         {
8783           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8784           throw INTERP_KERNEL::Exception(oss.str().c_str());
8785         }
8786       if(lgth>=work[-1])
8787         *work=lgth;
8788       else
8789         {
8790           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8791           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8792           throw INTERP_KERNEL::Exception(oss.str().c_str());
8793         }
8794     }
8795   arro->alloc(lgth,1);
8796   work=arro->getPointer();
8797   idsIt=idsOfSelectBg;
8798   for(std::size_t i=0;i<sz;i++,idsIt++)
8799     {
8800       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8801         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8802       else
8803         {
8804           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8805           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8806           throw INTERP_KERNEL::Exception(oss.str().c_str());
8807         }
8808     }
8809   arrOut=arro.retn();
8810   arrIndexOut=arrIo.retn();
8811 }
8812
8813 /*!
8814  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8815  * 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 ).
8816  * The selection of extraction is done standardly in new2old format.
8817  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8818  *
8819  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8820  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8821  * \param [in] arrIn arr origin array from which the extraction will be done.
8822  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8823  * \param [out] arrOut the resulting array
8824  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8825  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8826  */
8827 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8828                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8829 {
8830   if(!arrIn || !arrIndxIn)
8831     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8832   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8833   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8835   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8836   const int *arrInPtr=arrIn->getConstPointer();
8837   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8838   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8839   if(nbOfGrps<0)
8840     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8841   int maxSizeOfArr=arrIn->getNumberOfTuples();
8842   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8843   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8844   arrIo->alloc((int)(sz+1),1);
8845   int idsIt=idsOfSelectStart;
8846   int *work=arrIo->getPointer();
8847   *work++=0;
8848   int lgth=0;
8849   for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8850     {
8851       if(idsIt>=0 && idsIt<nbOfGrps)
8852         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8853       else
8854         {
8855           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8856           throw INTERP_KERNEL::Exception(oss.str().c_str());
8857         }
8858       if(lgth>=work[-1])
8859         *work=lgth;
8860       else
8861         {
8862           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8863           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8864           throw INTERP_KERNEL::Exception(oss.str().c_str());
8865         }
8866     }
8867   arro->alloc(lgth,1);
8868   work=arro->getPointer();
8869   idsIt=idsOfSelectStart;
8870   for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8871     {
8872       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8873         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8874       else
8875         {
8876           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8877           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8878           throw INTERP_KERNEL::Exception(oss.str().c_str());
8879         }
8880     }
8881   arrOut=arro.retn();
8882   arrIndexOut=arrIo.retn();
8883 }
8884
8885 /*!
8886  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8887  * 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
8888  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8889  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8890  *
8891  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8892  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8893  * \param [in] arrIn arr origin array from which the extraction will be done.
8894  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8895  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8896  * \param [in] srcArrIndex index array of \b srcArr
8897  * \param [out] arrOut the resulting array
8898  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8899  * 
8900  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8901  */
8902 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8903                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8904                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8905 {
8906   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8908   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8909   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8910   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8911   std::vector<bool> v(nbOfTuples,true);
8912   int offset=0;
8913   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8914   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8915   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8916     {
8917       if(*it>=0 && *it<nbOfTuples)
8918         {
8919           v[*it]=false;
8920           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8921         }
8922       else
8923         {
8924           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8925           throw INTERP_KERNEL::Exception(oss.str().c_str());
8926         }
8927     }
8928   srcArrIndexPtr=srcArrIndex->getConstPointer();
8929   arrIo->alloc(nbOfTuples+1,1);
8930   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8931   const int *arrInPtr=arrIn->getConstPointer();
8932   const int *srcArrPtr=srcArr->getConstPointer();
8933   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8934   int *arroPtr=arro->getPointer();
8935   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8936     {
8937       if(v[ii])
8938         {
8939           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8940           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8941         }
8942       else
8943         {
8944           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8945           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8946           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8947         }
8948     }
8949   arrOut=arro.retn();
8950   arrIndexOut=arrIo.retn();
8951 }
8952
8953 /*!
8954  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8955  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8956  *
8957  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8958  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8959  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8960  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8961  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8962  * \param [in] srcArrIndex index array of \b srcArr
8963  * 
8964  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8965  */
8966 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8967                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8968 {
8969   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8970     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8971   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8972   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8973   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8974   int *arrInOutPtr=arrInOut->getPointer();
8975   const int *srcArrPtr=srcArr->getConstPointer();
8976   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8977     {
8978       if(*it>=0 && *it<nbOfTuples)
8979         {
8980           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8981             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8982           else
8983             {
8984               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] !";
8985               throw INTERP_KERNEL::Exception(oss.str().c_str());
8986             }
8987         }
8988       else
8989         {
8990           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8991           throw INTERP_KERNEL::Exception(oss.str().c_str());
8992         }
8993     }
8994 }
8995
8996 /*!
8997  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8998  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8999  * 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]].
9000  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9001  * A negative value in \b arrIn means that it is ignored.
9002  * 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.
9003  * 
9004  * \param [in] arrIn arr origin array from which the extraction will be done.
9005  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9006  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9007  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9008  */
9009 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9010 {
9011   int seed=0,nbOfDepthPeelingPerformed=0;
9012   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9013 }
9014
9015 /*!
9016  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9017  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9018  * 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]].
9019  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9020  * A negative value in \b arrIn means that it is ignored.
9021  * 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.
9022  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9023  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9024  * \param [in] arrIn arr origin array from which the extraction will be done.
9025  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9026  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9027  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9028  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9029  * \sa MEDCouplingUMesh::partitionBySpreadZone
9030  */
9031 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9032 {
9033   nbOfDepthPeelingPerformed=0;
9034   if(!arrIndxIn)
9035     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9036   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9037   if(nbOfTuples<=0)
9038     {
9039       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9040       return ret;
9041     }
9042   //
9043   std::vector<bool> fetched(nbOfTuples,false);
9044   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9045 }
9046
9047 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)
9048 {
9049   nbOfDepthPeelingPerformed=0;
9050   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9051     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9052   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9053   std::vector<bool> fetched2(nbOfTuples,false);
9054   int i=0;
9055   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9056     {
9057       if(*seedElt>=0 && *seedElt<nbOfTuples)
9058         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9059       else
9060         { 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()); }
9061     }
9062   const int *arrInPtr=arrIn->getConstPointer();
9063   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9064   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9065   std::vector<int> idsToFetch1(seedBg,seedEnd);
9066   std::vector<int> idsToFetch2;
9067   std::vector<int> *idsToFetch=&idsToFetch1;
9068   std::vector<int> *idsToFetchOther=&idsToFetch2;
9069   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9070     {
9071       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9072         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9073           if(!fetched[*it2])
9074             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9075       std::swap(idsToFetch,idsToFetchOther);
9076       idsToFetchOther->clear();
9077       nbOfDepthPeelingPerformed++;
9078     }
9079   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9080   i=0;
9081   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9082   int *retPtr=ret->getPointer();
9083   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9084     if(*it)
9085       *retPtr++=i;
9086   return ret.retn();
9087 }
9088
9089 /*!
9090  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9091  * 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
9092  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9093  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9094  *
9095  * \param [in] start begin of set of ids of the input extraction (included)
9096  * \param [in] end end of set of ids of the input extraction (excluded)
9097  * \param [in] step step of the set of ids in range mode.
9098  * \param [in] arrIn arr origin array from which the extraction will be done.
9099  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9100  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9101  * \param [in] srcArrIndex index array of \b srcArr
9102  * \param [out] arrOut the resulting array
9103  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9104  * 
9105  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9106  */
9107 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9108                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9109                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9110 {
9111   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9112     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9113   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9114   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9115   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9116   int offset=0;
9117   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9118   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9119   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9120   int it=start;
9121   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9122     {
9123       if(it>=0 && it<nbOfTuples)
9124         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9125       else
9126         {
9127           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9128           throw INTERP_KERNEL::Exception(oss.str().c_str());
9129         }
9130     }
9131   srcArrIndexPtr=srcArrIndex->getConstPointer();
9132   arrIo->alloc(nbOfTuples+1,1);
9133   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9134   const int *arrInPtr=arrIn->getConstPointer();
9135   const int *srcArrPtr=srcArr->getConstPointer();
9136   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9137   int *arroPtr=arro->getPointer();
9138   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9139     {
9140       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9141       if(pos<0)
9142         {
9143           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9144           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9145         }
9146       else
9147         {
9148           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9149           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9150         }
9151     }
9152   arrOut=arro.retn();
9153   arrIndexOut=arrIo.retn();
9154 }
9155
9156 /*!
9157  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9158  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9159  *
9160  * \param [in] start begin of set of ids of the input extraction (included)
9161  * \param [in] end end of set of ids of the input extraction (excluded)
9162  * \param [in] step step of the set of ids in range mode.
9163  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9164  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9165  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9166  * \param [in] srcArrIndex index array of \b srcArr
9167  * 
9168  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9169  */
9170 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9171                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9172 {
9173   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9174     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9175   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9176   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9177   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9178   int *arrInOutPtr=arrInOut->getPointer();
9179   const int *srcArrPtr=srcArr->getConstPointer();
9180   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9181   int it=start;
9182   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9183     {
9184       if(it>=0 && it<nbOfTuples)
9185         {
9186           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9187             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9188           else
9189             {
9190               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9191               throw INTERP_KERNEL::Exception(oss.str().c_str());
9192             }
9193         }
9194       else
9195         {
9196           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9197           throw INTERP_KERNEL::Exception(oss.str().c_str());
9198         }
9199     }
9200 }
9201
9202 /*!
9203  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9204  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9205  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9206  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9207  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9208  * 
9209  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9210  */
9211 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9212 {
9213   checkFullyDefined();
9214   int mdim=getMeshDimension();
9215   int spaceDim=getSpaceDimension();
9216   if(mdim!=spaceDim)
9217     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9218   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9219   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9220   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9221   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9222   ret->setCoords(getCoords());
9223   ret->allocateCells((int)partition.size());
9224   //
9225   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9226     {
9227       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9228       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9229       switch(mdim)
9230         {
9231         case 2:
9232           cell=tmp->buildUnionOf2DMesh();
9233           break;
9234         case 3:
9235           cell=tmp->buildUnionOf3DMesh();
9236           break;
9237         default:
9238           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9239         }
9240       
9241       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9242     }
9243   //
9244   ret->finishInsertingCells();
9245   return ret.retn();
9246 }
9247
9248 /*!
9249  * This method partitions \b this into contiguous zone.
9250  * This method only needs a well defined connectivity. Coordinates are not considered here.
9251  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9252  */
9253 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9254 {
9255   int nbOfCellsCur=getNumberOfCells();
9256   std::vector<DataArrayInt *> ret;
9257   if(nbOfCellsCur<=0)
9258     return ret;
9259   DataArrayInt *neigh=0,*neighI=0;
9260   computeNeighborsOfCells(neigh,neighI);
9261   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9262   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9263   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9264   int seed=0;
9265   while(seed<nbOfCellsCur)
9266     {
9267       int nbOfPeelPerformed=0;
9268       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9269       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9270     }
9271   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9272     ret.push_back((*it).retn());
9273   return ret;
9274 }
9275
9276 /*!
9277  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9278  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9279  *
9280  * \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.
9281  * \return a newly allocated DataArrayInt to be managed by the caller.
9282  * \throw In case of \a code has not the right format (typically of size 3*n)
9283  */
9284 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9285 {
9286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9287   std::size_t nb=code.size()/3;
9288   if(code.size()%3!=0)
9289     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9290   ret->alloc((int)nb,2);
9291   int *retPtr=ret->getPointer();
9292   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9293     {
9294       retPtr[0]=code[3*i+2];
9295       retPtr[1]=code[3*i+2]+code[3*i+1];
9296     }
9297   return ret.retn();
9298 }
9299
9300 /*!
9301  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9302  * All cells in \a this are expected to be linear 3D cells.
9303  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9304  * It leads to an increase to number of cells.
9305  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9306  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
9307  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9308  *
9309  * \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.
9310  *                      For all other cells, the splitting policy will be ignored.
9311  * \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. 
9312  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9313  *          an id of old cell producing it. The caller is to delete this array using
9314  *         decrRef() as it is no more needed.
9315  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9316  * 
9317  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9318  * \throw If \a this is not fully constituted with linear 3D cells.
9319  * \sa MEDCouplingUMesh::simplexize
9320  */
9321 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const throw(INTERP_KERNEL::Exception)
9322 {
9323   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9324   checkConnectivityFullyDefined();
9325   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9326     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9327   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9328   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
9329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9330   int *retPt(ret->getPointer());
9331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9332   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9333   const int *oldc(_nodal_connec->begin());
9334   const int *oldci(_nodal_connec_index->begin());
9335   const double *coords(_coords->begin());
9336   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9337     {
9338       std::vector<int> a; std::vector<double> b;
9339       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9340       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9341       const int *aa(&a[0]);
9342       if(!b.empty())
9343         {
9344           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9345             if(*it<0)
9346               *it=(-(*(it))-1+nbNodes);
9347           addPts->insertAtTheEnd(b.begin(),b.end());
9348           nbNodes+=(int)b.size()/3;
9349         }
9350       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9351         newConn->insertAtTheEnd(aa,aa+4);
9352     }
9353   if(!addPts->empty())
9354     {
9355       addPts->rearrange(3);
9356       nbOfAdditionalPoints=addPts->getNumberOfTuples();
9357       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9358       ret0->setCoords(addPts);
9359     }
9360   else
9361     {
9362       nbOfAdditionalPoints=0;
9363       ret0->setCoords(getCoords());
9364     }
9365   ret0->setNodalConnectivity(newConn);
9366   //
9367   ret->computeOffsets2();
9368   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9369   return ret0.retn();
9370 }
9371
9372 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9373                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9374 {
9375   if(mesh)
9376     {
9377       mesh->incrRef();
9378       _nb_cell=mesh->getNumberOfCells();
9379     }
9380 }
9381
9382 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9383 {
9384   if(_mesh)
9385     _mesh->decrRef();
9386   if(_own_cell)
9387     delete _cell;
9388 }
9389
9390 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9391                                                                                                                                _own_cell(false),_cell_id(bg-1),
9392                                                                                                                                _nb_cell(end)
9393 {
9394   if(mesh)
9395     mesh->incrRef();
9396 }
9397
9398 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9399 {
9400   _cell_id++;
9401   if(_cell_id<_nb_cell)
9402     {
9403       _cell->next();
9404       return _cell;
9405     }
9406   else
9407     return 0;
9408 }
9409
9410 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9411 {
9412   if(_mesh)
9413     _mesh->incrRef();
9414 }
9415
9416 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9417 {
9418   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9419 }
9420
9421 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9422 {
9423   if(_mesh)
9424     _mesh->decrRef();
9425 }
9426
9427 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9428                                                                                                                                                                   _itc(itc),
9429                                                                                                                                                                   _bg(bg),_end(end)
9430 {
9431   if(_mesh)
9432     _mesh->incrRef();
9433 }
9434
9435 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9436 {
9437   if(_mesh)
9438     _mesh->decrRef();
9439 }
9440
9441 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9442 {
9443   return _type;
9444 }
9445
9446 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9447 {
9448   return _end-_bg;
9449 }
9450
9451 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9452 {
9453   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9454 }
9455
9456 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9457 {
9458   if(mesh)
9459     {
9460       mesh->incrRef();
9461       _nb_cell=mesh->getNumberOfCells();
9462     }
9463 }
9464
9465 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9466 {
9467   if(_mesh)
9468     _mesh->decrRef();
9469   delete _cell;
9470 }
9471
9472 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9473 {
9474   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9475   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9476   if(_cell_id<_nb_cell)
9477     {
9478       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9479       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9480       int startId=_cell_id;
9481       _cell_id+=nbOfElems;
9482       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9483     }
9484   else
9485     return 0;
9486 }
9487
9488 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9489 {
9490   if(mesh)
9491     {
9492       _conn=mesh->getNodalConnectivity()->getPointer();
9493       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9494     }
9495 }
9496
9497 void MEDCouplingUMeshCell::next()
9498 {
9499   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9500     {
9501       _conn+=_conn_lgth;
9502       _conn_indx++;
9503     }
9504   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9505 }
9506
9507 std::string MEDCouplingUMeshCell::repr() const
9508 {
9509   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9510     {
9511       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9512       oss << " : ";
9513       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9514       return oss.str();
9515     }
9516   else
9517     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9518 }
9519
9520 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9521 {
9522   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9523     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9524   else
9525     return INTERP_KERNEL::NORM_ERROR;
9526 }
9527
9528 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9529 {
9530   lgth=_conn_lgth;
9531   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9532     return _conn;
9533   else
9534     return 0;
9535 }