Salome HOME
addition of MEDCouplingUMesh::conformize2D to conformize a 2D mesh
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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 "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.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 std::string& 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
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)
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::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildren() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
128   if(_nodal_connec)
129     ret.push_back(_nodal_connec);
130   if(_nodal_connec_index)
131     ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
247         {
248           int nodeId=*w;
249           if(nodeId>=0)
250             {
251               if(nodeId>=nbOfNodes)
252                 {
253                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254                   throw INTERP_KERNEL::Exception(oss.str().c_str());
255                 }
256             }
257           else if(nodeId<-1)
258             {
259               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260               throw INTERP_KERNEL::Exception(oss.str().c_str());
261             }
262           else
263             {
264               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
265                 {
266                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267                   throw INTERP_KERNEL::Exception(oss.str().c_str());
268                 }
269             }
270         }
271     }
272 }
273
274
275 /*!
276  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277  * then \a this mesh is most probably is writable, exchangeable and available for all
278  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
279  *  \param [in] eps - a not used parameter.
280  *  \throw If the mesh dimension is not set.
281  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
282  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283  *  \throw If the connectivity data array has more than one component.
284  *  \throw If the connectivity data array has a named component.
285  *  \throw If the connectivity index data array has more than one component.
286  *  \throw If the connectivity index data array has a named component.
287  *  \throw If number of nodes defining an element does not correspond to the type of element.
288  *  \throw If the nodal connectivity includes an invalid node id.
289  */
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
291 {
292   checkCoherency1(eps);
293 }
294
295 /*!
296  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297  * elements contained in the mesh. For more info on the mesh dimension see
298  * \ref MEDCouplingUMeshPage.
299  *  \param [in] meshDim - a new mesh dimension.
300  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
301  */
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
303 {
304   if(meshDim<-1 || meshDim>3)
305     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
306   _mesh_dim=meshDim;
307   declareAsNew();
308 }
309
310 /*!
311  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
314  *
315  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
316  *
317  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
318  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
319  */
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
321 {
322   if(nbOfCells<0)
323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324   if(_nodal_connec_index)
325     {
326       _nodal_connec_index->decrRef();
327     }
328   if(_nodal_connec)
329     {
330       _nodal_connec->decrRef();
331     }
332   _nodal_connec_index=DataArrayInt::New();
333   _nodal_connec_index->reserve(nbOfCells+1);
334   _nodal_connec_index->pushBackSilent(0);
335   _nodal_connec=DataArrayInt::New();
336   _nodal_connec->reserve(2*nbOfCells);
337   _types.clear();
338   declareAsNew();
339 }
340
341 /*!
342  * Appends a cell to the connectivity array. For deeper understanding what is
343  * happening see \ref MEDCouplingUMeshNodalConnectivity.
344  *  \param [in] type - type of cell to add.
345  *  \param [in] size - number of nodes constituting this cell.
346  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
347  * 
348  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
349  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
350  */
351 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
352 {
353   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
354   if(_nodal_connec_index==0)
355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
356   if((int)cm.getDimension()==_mesh_dim)
357     {
358       if(!cm.isDynamic())
359         if(size!=(int)cm.getNumberOfNodes())
360           {
361             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
362             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
363             throw INTERP_KERNEL::Exception(oss.str().c_str());
364           }
365       int idx=_nodal_connec_index->back();
366       int val=idx+size+1;
367       _nodal_connec_index->pushBackSilent(val);
368       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
369       _types.insert(type);
370     }
371   else
372     {
373       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
374       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
375       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
376       throw INTERP_KERNEL::Exception(oss.str().c_str());
377     }
378 }
379
380 /*!
381  * Compacts data arrays to release unused memory. This method is to be called after
382  * finishing cell insertion using \a this->insertNextCell().
383  * 
384  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
385  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
386  */
387 void MEDCouplingUMesh::finishInsertingCells()
388 {
389   _nodal_connec->pack();
390   _nodal_connec_index->pack();
391   _nodal_connec->declareAsNew();
392   _nodal_connec_index->declareAsNew();
393   updateTime();
394 }
395
396 /*!
397  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
398  * Useful for python users.
399  */
400 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
401 {
402   return new MEDCouplingUMeshCellIterator(this);
403 }
404
405 /*!
406  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
407  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
408  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
409  * Useful for python users.
410  */
411 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
412 {
413   if(!checkConsecutiveCellTypes())
414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
415   return new MEDCouplingUMeshCellByTypeEntry(this);
416 }
417
418 /*!
419  * Returns a set of all cell types available in \a this mesh.
420  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
421  * \warning this method does not throw any exception even if \a this is not defined.
422  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
423  */
424 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
425 {
426   return _types;
427 }
428
429 /*!
430  * This method returns the sorted list of geometric types in \a this.
431  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
432  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
433  *
434  * \throw if connectivity in \a this is not correctly defined.
435  *  
436  * \sa MEDCouplingMesh::getAllGeoTypes
437  */
438 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
439 {
440   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
441   checkConnectivityFullyDefined();
442   int nbOfCells(getNumberOfCells());
443   if(nbOfCells==0)
444     return ret;
445   if(getMeshLength()<1)
446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
447   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
448   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
449   for(int i=1;i<nbOfCells;i++,ci++)
450     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
451       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
452   return ret;
453 }
454
455 /*!
456  * This method is a method that compares \a this and \a other.
457  * This method compares \b all attributes, even names and component names.
458  */
459 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
460 {
461   if(!other)
462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
463   std::ostringstream oss; oss.precision(15);
464   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
465   if(!otherC)
466     {
467       reason="mesh given in input is not castable in MEDCouplingUMesh !";
468       return false;
469     }
470   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
471     return false;
472   if(_mesh_dim!=otherC->_mesh_dim)
473     {
474       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
475       reason=oss.str();
476       return false;
477     }
478   if(_types!=otherC->_types)
479     {
480       oss << "umesh geometric type mismatch :\nThis geometric types are :";
481       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
482         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
483       oss << "\nOther geometric types are :";
484       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
485         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
486       reason=oss.str();
487       return false;
488     }
489   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
490     if(_nodal_connec==0 || otherC->_nodal_connec==0)
491       {
492         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
493         return false;
494       }
495   if(_nodal_connec!=otherC->_nodal_connec)
496     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
497       {
498         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
499         return false;
500       }
501   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
502     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
503       {
504         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
505         return false;
506       }
507   if(_nodal_connec_index!=otherC->_nodal_connec_index)
508     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
509       {
510         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
511         return false;
512       }
513   return true;
514 }
515
516 /*!
517  * Checks if data arrays of this mesh (node coordinates, nodal
518  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
519  * not considered.
520  *  \param [in] other - the mesh to compare with.
521  *  \param [in] prec - precision value used to compare node coordinates.
522  *  \return bool - \a true if the two meshes are same.
523  */
524 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
525 {
526   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
527   if(!otherC)
528     return false;
529   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
530     return false;
531   if(_mesh_dim!=otherC->_mesh_dim)
532     return false;
533   if(_types!=otherC->_types)
534     return false;
535   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
536     if(_nodal_connec==0 || otherC->_nodal_connec==0)
537       return false;
538   if(_nodal_connec!=otherC->_nodal_connec)
539     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
540       return false;
541   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
542     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
543       return false;
544   if(_nodal_connec_index!=otherC->_nodal_connec_index)
545     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
546       return false;
547   return true;
548 }
549
550 /*!
551  * Checks if \a this and \a other meshes are geometrically equivalent with high
552  * probability, else an exception is thrown. The meshes are considered equivalent if
553  * (1) meshes contain the same number of nodes and the same number of elements of the
554  * same types (2) three cells of the two meshes (first, last and middle) are based
555  * on coincident nodes (with a specified precision).
556  *  \param [in] other - the mesh to compare with.
557  *  \param [in] prec - the precision used to compare nodes of the two meshes.
558  *  \throw If the two meshes do not match.
559  */
560 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
561 {
562  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
563  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
564   if(!otherC)
565     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
566 }
567
568 /*!
569  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
570  * cells each node belongs to.
571  * \warning For speed reasons, this method does not check if node ids in the nodal
572  *          connectivity correspond to the size of node coordinates array.
573  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
574  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
575  *        dividing cell ids in \a revNodal into groups each referring to one
576  *        node. Its every element (except the last one) is an index pointing to the
577  *         first id of a group of cells. For example cells sharing the node #1 are 
578  *        described by following range of indices: 
579  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
580  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
581  *        Number of cells sharing the *i*-th node is
582  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
583  * \throw If the coordinates array is not set.
584  * \throw If the nodal connectivity of cells is not defined.
585  * 
586  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
587  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
588  */
589 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
590 {
591   checkFullyDefined();
592   int nbOfNodes=getNumberOfNodes();
593   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
594   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
595   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
596   const int *conn=_nodal_connec->getConstPointer();
597   const int *connIndex=_nodal_connec_index->getConstPointer();
598   int nbOfCells=getNumberOfCells();
599   int nbOfEltsInRevNodal=0;
600   for(int eltId=0;eltId<nbOfCells;eltId++)
601     {
602       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
603       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
604       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
605         if(*iter>=0)//for polyhedrons
606           {
607             nbOfEltsInRevNodal++;
608             revNodalIndxPtr[(*iter)+1]++;
609           }
610     }
611   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
612   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
613   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
614   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
615   for(int eltId=0;eltId<nbOfCells;eltId++)
616     {
617       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
618       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
619       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
620         if(*iter>=0)//for polyhedrons
621           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
622     }
623 }
624
625 /// @cond INTERNAL
626
627 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
628 {
629   return id;
630 }
631
632 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
633 {
634   if(!compute)
635     return id+1;
636   else
637     {
638       if(cm.getOrientationStatus(nb,conn1,conn2))
639         return id+1;
640       else
641         return -(id+1);
642     }
643 }
644
645 class MinusOneSonsGenerator
646 {
647 public:
648   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
649   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
650   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
651   static const int DELTA=1;
652 private:
653   const INTERP_KERNEL::CellModel& _cm;
654 };
655
656 class MinusOneSonsGeneratorBiQuadratic
657 {
658 public:
659   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
660   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
661   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
662   static const int DELTA=1;
663 private:
664   const INTERP_KERNEL::CellModel& _cm;
665 };
666
667 class MinusTwoSonsGenerator
668 {
669 public:
670   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
671   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
672   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
673   static const int DELTA=2;
674 private:
675   const INTERP_KERNEL::CellModel& _cm;
676 };
677
678 /// @endcond
679
680 /*!
681  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
682  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
683  * describing correspondence between cells of \a this and the result meshes are
684  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
685  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
686  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
687  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
688  * \warning For speed reasons, this method does not check if node ids in the nodal
689  *          connectivity correspond to the size of node coordinates array.
690  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
691  *          to write this mesh to the MED file, its cells must be sorted using
692  *          sortCellsInMEDFileFrmt().
693  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
694  *         each cell of \a this mesh.
695  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
696  *        dividing cell ids in \a desc into groups each referring to one
697  *        cell of \a this mesh. Its every element (except the last one) is an index
698  *        pointing to the first id of a group of cells. For example cells of the
699  *        result mesh bounding the cell #1 of \a this mesh are described by following
700  *        range of indices:
701  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
702  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
703  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
704  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
705  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
706  *         by each cell of the result mesh.
707  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
708  *        in the result mesh,
709  *        dividing cell ids in \a revDesc into groups each referring to one
710  *        cell of the result mesh the same way as \a descIndx divides \a desc.
711  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
712  *        delete this mesh using decrRef() as it is no more needed.
713  *  \throw If the coordinates array is not set.
714  *  \throw If the nodal connectivity of cells is node defined.
715  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
716  *         revDescIndx == NULL.
717  * 
718  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
719  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
720  * \sa buildDescendingConnectivity2()
721  */
722 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
723 {
724   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
725 }
726
727 /*!
728  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
729  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
730  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
731  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
732  * \sa MEDCouplingUMesh::buildDescendingConnectivity
733  */
734 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
735 {
736   checkFullyDefined();
737   if(getMeshDimension()!=3)
738     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
739   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
740 }
741
742 /*!
743  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
744  * this->getMeshDimension(), that bound cells of \a this mesh. In
745  * addition arrays describing correspondence between cells of \a this and the result
746  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
747  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
748  *  mesh. This method differs from buildDescendingConnectivity() in that apart
749  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
750  * result meshes. So a positive id means that order of nodes in corresponding cells
751  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
752  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
753  * i.e. cell ids are one-based.
754  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
755  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
756  * \warning For speed reasons, this method does not check if node ids in the nodal
757  *          connectivity correspond to the size of node coordinates array.
758  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
759  *          to write this mesh to the MED file, its cells must be sorted using
760  *          sortCellsInMEDFileFrmt().
761  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
762  *         each cell of \a this mesh.
763  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
764  *        dividing cell ids in \a desc into groups each referring to one
765  *        cell of \a this mesh. Its every element (except the last one) is an index
766  *        pointing to the first id of a group of cells. For example cells of the
767  *        result mesh bounding the cell #1 of \a this mesh are described by following
768  *        range of indices:
769  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
770  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
771  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
772  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
773  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
774  *         by each cell of the result mesh.
775  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
776  *        in the result mesh,
777  *        dividing cell ids in \a revDesc into groups each referring to one
778  *        cell of the result mesh the same way as \a descIndx divides \a desc.
779  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
780  *        shares the node coordinates array with \a this mesh. The caller is to
781  *        delete this mesh using decrRef() as it is no more needed.
782  *  \throw If the coordinates array is not set.
783  *  \throw If the nodal connectivity of cells is node defined.
784  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
785  *         revDescIndx == NULL.
786  * 
787  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
788  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
789  * \sa buildDescendingConnectivity()
790  */
791 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
792 {
793   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
794 }
795
796 /*!
797  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
798  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
799  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
800  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
801  *
802  * \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
803  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
804  * \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.
805  */
806 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
807 {
808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
812   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
813   meshDM1=0;
814   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
815 }
816
817 /*!
818  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
819  * 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,
820  * excluding a set of meshdim-1 cells in input descending connectivity.
821  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
822  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
823  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
824  *
825  * \param [in] desc descending connectivity array.
826  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
827  * \param [in] revDesc reverse descending connectivity array.
828  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
829  * \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
830  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
831  * \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.
832  */
833 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
834                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
835 {
836   if(!desc || !descIndx || !revDesc || !revDescIndx)
837     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
838   const int *descPtr=desc->getConstPointer();
839   const int *descIPtr=descIndx->getConstPointer();
840   const int *revDescPtr=revDesc->getConstPointer();
841   const int *revDescIPtr=revDescIndx->getConstPointer();
842   //
843   int nbCells=descIndx->getNumberOfTuples()-1;
844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
845   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
846   int *out1Ptr=out1->getPointer();
847   *out1Ptr++=0;
848   out0->reserve(desc->getNumberOfTuples());
849   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
850     {
851       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
852         {
853           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
854           s.erase(i);
855           out0->insertAtTheEnd(s.begin(),s.end());
856         }
857       *out1Ptr=out0->getNumberOfTuples();
858     }
859   neighbors=out0.retn();
860   neighborsIndx=out1.retn();
861 }
862
863 /// @cond INTERNAL
864
865 /*!
866  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
867  * For speed reasons no check of this will be done.
868  */
869 template<class SonsGenerator>
870 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
871 {
872   if(!desc || !descIndx || !revDesc || !revDescIndx)
873     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
874   checkConnectivityFullyDefined();
875   int nbOfCells=getNumberOfCells();
876   int nbOfNodes=getNumberOfNodes();
877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
878   int *revNodalIndxPtr=revNodalIndx->getPointer();
879   const int *conn=_nodal_connec->getConstPointer();
880   const int *connIndex=_nodal_connec_index->getConstPointer();
881   std::string name="Mesh constituent of "; name+=getName();
882   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
883   ret->setCoords(getCoords());
884   ret->allocateCells(2*nbOfCells);
885   descIndx->alloc(nbOfCells+1,1);
886   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
887   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
888   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
889     {
890       int pos=connIndex[eltId];
891       int posP1=connIndex[eltId+1];
892       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
893       SonsGenerator sg(cm);
894       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
895       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
896       for(unsigned i=0;i<nbOfSons;i++)
897         {
898           INTERP_KERNEL::NormalizedCellType cmsId;
899           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
900           for(unsigned k=0;k<nbOfNodesSon;k++)
901             if(tmp[k]>=0)
902               revNodalIndxPtr[tmp[k]+1]++;
903           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
904           revDesc2->pushBackSilent(eltId);
905         }
906       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
907     }
908   int nbOfCellsM1=ret->getNumberOfCells();
909   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
910   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
911   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
912   int *revNodalPtr=revNodal->getPointer();
913   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
914   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
915   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
916     {
917       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
918       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
919       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
920         if(*iter>=0)//for polyhedrons
921           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
922     }
923   //
924   DataArrayInt *commonCells=0,*commonCellsI=0;
925   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
926   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
927   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
928   int newNbOfCellsM1=-1;
929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
930                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
931   std::vector<bool> isImpacted(nbOfCellsM1,false);
932   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
933     for(int work2=work[0];work2!=work[1];work2++)
934       isImpacted[commonCellsPtr[work2]]=true;
935   const int *o2nM1Ptr=o2nM1->getConstPointer();
936   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
937   const int *n2oM1Ptr=n2oM1->getConstPointer();
938   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
939   ret2->copyTinyInfoFrom(this);
940   desc->alloc(descIndx->back(),1);
941   int *descPtr=desc->getPointer();
942   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
943   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
944     {
945       if(!isImpacted[i])
946         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
947       else
948         {
949           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
950             {
951               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
952               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
953             }
954           else
955             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
956         }
957     }
958   revDesc->reserve(newNbOfCellsM1);
959   revDescIndx->alloc(newNbOfCellsM1+1,1);
960   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
961   const int *revDesc2Ptr=revDesc2->getConstPointer();
962   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
963     {
964       int oldCellIdM1=n2oM1Ptr[i];
965       if(!isImpacted[oldCellIdM1])
966         {
967           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
968           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
969         }
970       else
971         {
972           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
973             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
974           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
975           commonCellsIPtr++;
976         }
977     }
978   //
979   return ret2.retn();
980 }
981
982 struct MEDCouplingAccVisit
983 {
984   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
985   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
986   int _new_nb_of_nodes;
987 };
988
989 /// @endcond
990
991 /*!
992  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
993  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
994  * array of cell ids. Pay attention that after conversion all algorithms work slower
995  * with \a this mesh than before conversion. <br> If an exception is thrown during the
996  * conversion due presence of invalid ids in the array of cells to convert, as a
997  * result \a this mesh contains some already converted elements. In this case the 2D
998  * mesh remains valid but 3D mesh becomes \b inconsistent!
999  *  \warning This method can significantly modify the order of geometric types in \a this,
1000  *          hence, to write this mesh to the MED file, its cells must be sorted using
1001  *          sortCellsInMEDFileFrmt().
1002  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1003  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1004  *         cellIdsToConvertBg.
1005  *  \throw If the coordinates array is not set.
1006  *  \throw If the nodal connectivity of cells is node defined.
1007  *  \throw If dimension of \a this mesh is not either 2 or 3.
1008  *
1009  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1010  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1011  */
1012 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1013 {
1014   checkFullyDefined();
1015   int dim=getMeshDimension();
1016   if(dim<2 || dim>3)
1017     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1018   int nbOfCells(getNumberOfCells());
1019   if(dim==2)
1020     {
1021       const int *connIndex=_nodal_connec_index->getConstPointer();
1022       int *conn=_nodal_connec->getPointer();
1023       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1024         {
1025           if(*iter>=0 && *iter<nbOfCells)
1026             {
1027               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1028               if(!cm.isQuadratic())
1029                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1030               else
1031                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1032             }
1033           else
1034             {
1035               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1036               oss << " in range [0," << nbOfCells << ") !";
1037               throw INTERP_KERNEL::Exception(oss.str().c_str());
1038             }
1039         }
1040     }
1041   else
1042     {
1043       int *connIndex(_nodal_connec_index->getPointer());
1044       const int *connOld(_nodal_connec->getConstPointer());
1045       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1046       std::vector<bool> toBeDone(nbOfCells,false);
1047       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1048         {
1049           if(*iter>=0 && *iter<nbOfCells)
1050             toBeDone[*iter]=true;
1051           else
1052             {
1053               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1054               oss << " in range [0," << nbOfCells << ") !";
1055               throw INTERP_KERNEL::Exception(oss.str().c_str());
1056             }
1057         }
1058       for(int cellId=0;cellId<nbOfCells;cellId++)
1059         {
1060           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1061           int lgthOld(posP1-pos-1);
1062           if(toBeDone[cellId])
1063             {
1064               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1065               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1066               int *tmp(new int[nbOfFaces*lgthOld+1]);
1067               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1068               for(unsigned j=0;j<nbOfFaces;j++)
1069                 {
1070                   INTERP_KERNEL::NormalizedCellType type;
1071                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1072                   work+=offset;
1073                   *work++=-1;
1074                 }
1075               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1076               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1077               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1078               delete [] tmp;
1079             }
1080           else
1081             {
1082               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1083               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1084             }
1085         }
1086       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1087     }
1088   computeTypes();
1089 }
1090
1091 /*!
1092  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1093  * polyhedrons (if \a this is a 3D mesh).
1094  *  \warning As this method is purely for user-friendliness and no optimization is
1095  *          done to avoid construction of a useless vector, this method can be costly
1096  *          in memory.
1097  *  \throw If the coordinates array is not set.
1098  *  \throw If the nodal connectivity of cells is node defined.
1099  *  \throw If dimension of \a this mesh is not either 2 or 3.
1100  */
1101 void MEDCouplingUMesh::convertAllToPoly()
1102 {
1103   int nbOfCells=getNumberOfCells();
1104   std::vector<int> cellIds(nbOfCells);
1105   for(int i=0;i<nbOfCells;i++)
1106     cellIds[i]=i;
1107   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1108 }
1109
1110 /*!
1111  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1112  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1113  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1114  * base facet of the volume and the second half of nodes describes an opposite facet
1115  * having the same number of nodes as the base one. This method converts such
1116  * connectivity to a valid polyhedral format where connectivity of each facet is
1117  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1118  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1119  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1120  * a correct orientation of the first facet of a polyhedron, else orientation of a
1121  * corrected cell is reverse.<br>
1122  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1123  * it releases the user from boring description of polyhedra connectivity in the valid
1124  * format.
1125  *  \throw If \a this->getMeshDimension() != 3.
1126  *  \throw If \a this->getSpaceDimension() != 3.
1127  *  \throw If the nodal connectivity of cells is not defined.
1128  *  \throw If the coordinates array is not set.
1129  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1130  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1131  *
1132  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1133  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1134  */
1135 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1136 {
1137   checkFullyDefined();
1138   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1139     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1140   int nbOfCells=getNumberOfCells();
1141   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1142   newCi->alloc(nbOfCells+1,1);
1143   int *newci=newCi->getPointer();
1144   const int *ci=_nodal_connec_index->getConstPointer();
1145   const int *c=_nodal_connec->getConstPointer();
1146   newci[0]=0;
1147   for(int i=0;i<nbOfCells;i++)
1148     {
1149       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1150       if(type==INTERP_KERNEL::NORM_POLYHED)
1151         {
1152           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1153             {
1154               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1155               throw INTERP_KERNEL::Exception(oss.str().c_str());
1156             }
1157           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1158           if(n2%2!=0)
1159             {
1160               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 !";
1161               throw INTERP_KERNEL::Exception(oss.str().c_str());
1162             }
1163           int n1=(int)(n2/2);
1164           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)
1165         }
1166       else
1167         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1168     }
1169   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1170   newC->alloc(newci[nbOfCells],1);
1171   int *newc=newC->getPointer();
1172   for(int i=0;i<nbOfCells;i++)
1173     {
1174       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1175       if(type==INTERP_KERNEL::NORM_POLYHED)
1176         {
1177           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1178           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1179           *newc++=-1;
1180           for(std::size_t j=0;j<n1;j++)
1181             {
1182               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1183               newc[n1+5*j]=-1;
1184               newc[n1+5*j+1]=c[ci[i]+1+j];
1185               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1186               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1187               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1188             }
1189           newc+=n1*6;
1190         }
1191       else
1192         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1193     }
1194   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1195   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1196 }
1197
1198
1199 /*!
1200  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1201  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1202  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1203  *          to write this mesh to the MED file, its cells must be sorted using
1204  *          sortCellsInMEDFileFrmt().
1205  * \return \c true if at least one cell has been converted, \c false else. In the
1206  *         last case the nodal connectivity remains unchanged.
1207  * \throw If the coordinates array is not set.
1208  * \throw If the nodal connectivity of cells is not defined.
1209  * \throw If \a this->getMeshDimension() < 0.
1210  */
1211 bool MEDCouplingUMesh::unPolyze()
1212 {
1213   checkFullyDefined();
1214   int mdim=getMeshDimension();
1215   if(mdim<0)
1216     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1217   if(mdim<=1)
1218     return false;
1219   int nbOfCells=getNumberOfCells();
1220   if(nbOfCells<1)
1221     return false;
1222   int initMeshLgth=getMeshLength();
1223   int *conn=_nodal_connec->getPointer();
1224   int *index=_nodal_connec_index->getPointer();
1225   int posOfCurCell=0;
1226   int newPos=0;
1227   int lgthOfCurCell;
1228   bool ret=false;
1229   for(int i=0;i<nbOfCells;i++)
1230     {
1231       lgthOfCurCell=index[i+1]-posOfCurCell;
1232       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1233       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1234       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1235       int newLgth;
1236       if(cm.isDynamic())
1237         {
1238           switch(cm.getDimension())
1239             {
1240             case 2:
1241               {
1242                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1243                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1244                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1245                 break;
1246               }
1247             case 3:
1248               {
1249                 int nbOfFaces,lgthOfPolyhConn;
1250                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1251                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1252                 break;
1253               }
1254             case 1:
1255               {
1256                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1257                 break;
1258               }
1259             }
1260           ret=ret || (newType!=type);
1261           conn[newPos]=newType;
1262           newPos+=newLgth+1;
1263           posOfCurCell=index[i+1];
1264           index[i+1]=newPos;
1265         }
1266       else
1267         {
1268           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1269           newPos+=lgthOfCurCell;
1270           posOfCurCell+=lgthOfCurCell;
1271           index[i+1]=newPos;
1272         }
1273     }
1274   if(newPos!=initMeshLgth)
1275     _nodal_connec->reAlloc(newPos);
1276   if(ret)
1277     computeTypes();
1278   return ret;
1279 }
1280
1281 /*!
1282  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1283  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1284  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1285  *
1286  * \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 
1287  *             precision.
1288  */
1289 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1290 {
1291   checkFullyDefined();
1292   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1293     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1294   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1295   coords->recenterForMaxPrecision(eps);
1296   //
1297   int nbOfCells=getNumberOfCells();
1298   const int *conn=_nodal_connec->getConstPointer();
1299   const int *index=_nodal_connec_index->getConstPointer();
1300   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1301   connINew->alloc(nbOfCells+1,1);
1302   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1303   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1304   bool changed=false;
1305   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1306     {
1307       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1308         {
1309           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1310           changed=true;
1311         }
1312       else
1313         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1314       *connINewPtr=connNew->getNumberOfTuples();
1315     }
1316   if(changed)
1317     setConnectivity(connNew,connINew,false);
1318 }
1319
1320 /*!
1321  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1322  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1323  * the format of returned DataArrayInt instance.
1324  * 
1325  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1326  * \sa MEDCouplingUMesh::getNodeIdsInUse
1327  */
1328 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1329 {
1330   checkConnectivityFullyDefined();
1331   int nbOfCells=getNumberOfCells();
1332   const int *connIndex=_nodal_connec_index->getConstPointer();
1333   const int *conn=_nodal_connec->getConstPointer();
1334   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1335   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1336   std::vector<bool> retS(maxElt,false);
1337   for(int i=0;i<nbOfCells;i++)
1338     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1339       if(conn[j]>=0)
1340         retS[conn[j]]=true;
1341   int sz=0;
1342   for(int i=0;i<maxElt;i++)
1343     if(retS[i])
1344       sz++;
1345   DataArrayInt *ret=DataArrayInt::New();
1346   ret->alloc(sz,1);
1347   int *retPtr=ret->getPointer();
1348   for(int i=0;i<maxElt;i++)
1349     if(retS[i])
1350       *retPtr++=i;
1351   return ret;
1352 }
1353
1354 /*!
1355  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1356  * \sa MEDCouplingUMesh::getNodeIdsInUse
1357  */
1358 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1359 {
1360   int nbOfNodes=(int)nodeIdsInUse.size();
1361   int nbOfCells=getNumberOfCells();
1362   const int *connIndex=_nodal_connec_index->getConstPointer();
1363   const int *conn=_nodal_connec->getConstPointer();
1364   for(int i=0;i<nbOfCells;i++)
1365     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1366       if(conn[j]>=0)
1367         {
1368           if(conn[j]<nbOfNodes)
1369             nodeIdsInUse[conn[j]]=true;
1370           else
1371             {
1372               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1373               throw INTERP_KERNEL::Exception(oss.str().c_str());
1374             }
1375         }
1376 }
1377
1378 /*!
1379  * Finds nodes not used in any cell and returns an array giving a new id to every node
1380  * by excluding the unused nodes, for which the array holds -1. The result array is
1381  * a mapping in "Old to New" mode. 
1382  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1383  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1384  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1385  *          if the node is unused or a new id else. The caller is to delete this
1386  *          array using decrRef() as it is no more needed.  
1387  *  \throw If the coordinates array is not set.
1388  *  \throw If the nodal connectivity of cells is not defined.
1389  *  \throw If the nodal connectivity includes an invalid id.
1390  *
1391  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1392  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1393  * \sa computeNodeIdsAlg()
1394  */
1395 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1396 {
1397   nbrOfNodesInUse=-1;
1398   int nbOfNodes=getNumberOfNodes();
1399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1400   ret->alloc(nbOfNodes,1);
1401   int *traducer=ret->getPointer();
1402   std::fill(traducer,traducer+nbOfNodes,-1);
1403   int nbOfCells=getNumberOfCells();
1404   const int *connIndex=_nodal_connec_index->getConstPointer();
1405   const int *conn=_nodal_connec->getConstPointer();
1406   for(int i=0;i<nbOfCells;i++)
1407     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1408       if(conn[j]>=0)
1409         {
1410           if(conn[j]<nbOfNodes)
1411             traducer[conn[j]]=1;
1412           else
1413             {
1414               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1415               throw INTERP_KERNEL::Exception(oss.str().c_str());
1416             }
1417         }
1418   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1419   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1420   return ret.retn();
1421 }
1422
1423 /*!
1424  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1425  * For each cell in \b this the number of nodes constituting cell is computed.
1426  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1427  * So for pohyhedrons some nodes can be counted several times in the returned result.
1428  * 
1429  * \return a newly allocated array
1430  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1431  */
1432 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1433 {
1434   checkConnectivityFullyDefined();
1435   int nbOfCells=getNumberOfCells();
1436   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1437   ret->alloc(nbOfCells,1);
1438   int *retPtr=ret->getPointer();
1439   const int *conn=getNodalConnectivity()->getConstPointer();
1440   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1441   for(int i=0;i<nbOfCells;i++,retPtr++)
1442     {
1443       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1444         *retPtr=connI[i+1]-connI[i]-1;
1445       else
1446         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1447     }
1448   return ret.retn();
1449 }
1450
1451 /*!
1452  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1453  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1454  *
1455  * \return DataArrayInt * - new object to be deallocated by the caller.
1456  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1457  */
1458 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1459 {
1460   checkConnectivityFullyDefined();
1461   int nbOfCells=getNumberOfCells();
1462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1463   ret->alloc(nbOfCells,1);
1464   int *retPtr=ret->getPointer();
1465   const int *conn=getNodalConnectivity()->getConstPointer();
1466   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1467   for(int i=0;i<nbOfCells;i++,retPtr++)
1468     {
1469       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1470       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1471         *retPtr=(int)s.size();
1472       else
1473         {
1474           s.erase(-1);
1475           *retPtr=(int)s.size();
1476         }
1477     }
1478   return ret.retn();
1479 }
1480
1481 /*!
1482  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1483  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1484  * 
1485  * \return a newly allocated array
1486  */
1487 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1488 {
1489   checkConnectivityFullyDefined();
1490   int nbOfCells=getNumberOfCells();
1491   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1492   ret->alloc(nbOfCells,1);
1493   int *retPtr=ret->getPointer();
1494   const int *conn=getNodalConnectivity()->getConstPointer();
1495   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1496   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1497     {
1498       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1499       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1500     }
1501   return ret.retn();
1502 }
1503
1504 /*!
1505  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1506  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1507  * array mean that the corresponding old node is no more used. 
1508  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1509  *           this->getNumberOfNodes() before call of this method. The caller is to
1510  *           delete this array using decrRef() as it is no more needed. 
1511  *  \throw If the coordinates array is not set.
1512  *  \throw If the nodal connectivity of cells is not defined.
1513  *  \throw If the nodal connectivity includes an invalid id.
1514  *
1515  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1516  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1517  */
1518 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1519 {
1520   return MEDCouplingPointSet::zipCoordsTraducer();
1521 }
1522
1523 /*!
1524  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1525  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1526  */
1527 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1528 {
1529   switch(compType)
1530     {
1531     case 0:
1532       return AreCellsEqual0(conn,connI,cell1,cell2);
1533     case 1:
1534       return AreCellsEqual1(conn,connI,cell1,cell2);
1535     case 2:
1536       return AreCellsEqual2(conn,connI,cell1,cell2);
1537     case 3:
1538       return AreCellsEqual3(conn,connI,cell1,cell2);
1539     case 7:
1540       return AreCellsEqual7(conn,connI,cell1,cell2);
1541     }
1542   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1543 }
1544
1545 /*!
1546  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1547  */
1548 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1549 {
1550   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1551     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1552   return 0;
1553 }
1554
1555 /*!
1556  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1557  */
1558 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1559 {
1560   int sz=connI[cell1+1]-connI[cell1];
1561   if(sz==connI[cell2+1]-connI[cell2])
1562     {
1563       if(conn[connI[cell1]]==conn[connI[cell2]])
1564         {
1565           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1566           unsigned dim=cm.getDimension();
1567           if(dim!=3)
1568             {
1569               if(dim!=1)
1570                 {
1571                   int sz1=2*(sz-1);
1572                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1573                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1574                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1575                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1576                   return work!=tmp+sz1?1:0;
1577                 }
1578               else
1579                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1580             }
1581           else
1582             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1583         }
1584     }
1585   return 0;
1586 }
1587
1588 /*!
1589  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1590  */
1591 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1592 {
1593   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1594     {
1595       if(conn[connI[cell1]]==conn[connI[cell2]])
1596         {
1597           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1598           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1599           return s1==s2?1:0;
1600         }
1601     }
1602   return 0;
1603 }
1604
1605 /*!
1606  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1607  */
1608 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1609 {
1610   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1611     {
1612       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1613       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1614       return s1==s2?1:0;
1615     }
1616   return 0;
1617 }
1618
1619 /*!
1620  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1621  */
1622 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1623 {
1624   int sz=connI[cell1+1]-connI[cell1];
1625   if(sz==connI[cell2+1]-connI[cell2])
1626     {
1627       if(conn[connI[cell1]]==conn[connI[cell2]])
1628         {
1629           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1630           unsigned dim=cm.getDimension();
1631           if(dim!=3)
1632             {
1633               if(dim!=1)
1634                 {
1635                   int sz1=2*(sz-1);
1636                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1637                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1638                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1639                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1640                   if(work!=tmp+sz1)
1641                     return 1;
1642                   else
1643                     {
1644                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1645                       std::reverse_iterator<int *> it2((int *)tmp);
1646                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1647                         return 2;
1648                       else
1649                         return 0;
1650                     }
1651                   
1652                   return work!=tmp+sz1?1:0;
1653                 }
1654               else
1655                 {//case of SEG2 and SEG3
1656                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1657                     return 1;
1658                   if(!cm.isQuadratic())
1659                     {
1660                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1661                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1662                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1663                         return 2;
1664                       return 0;
1665                     }
1666                   else
1667                     {
1668                       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])
1669                         return 2;
1670                       return 0;
1671                     }
1672                 }
1673             }
1674           else
1675             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1676         }
1677     }
1678   return 0;
1679 }
1680
1681 /*!
1682  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1683  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1684  * and result remains unchanged.
1685  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1686  * If in 'candidates' pool -1 value is considered as an empty value.
1687  * WARNING this method returns only ONE set of result !
1688  */
1689 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1690 {
1691   if(candidates.size()<1)
1692     return false;
1693   bool ret=false;
1694   std::vector<int>::const_iterator iter=candidates.begin();
1695   int start=(*iter++);
1696   for(;iter!=candidates.end();iter++)
1697     {
1698       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1699       if(status!=0)
1700         {
1701           if(!ret)
1702             {
1703               result->pushBackSilent(start);
1704               ret=true;
1705             }
1706           if(status==1)
1707             result->pushBackSilent(*iter);
1708           else
1709             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1710         }
1711     }
1712   return ret;
1713 }
1714
1715 /*!
1716  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1717  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1718  *
1719  * \param [in] compType input specifying the technique used to compare cells each other.
1720  *   - 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.
1721  *   - 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)
1722  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1723  *   - 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
1724  * can be used for users not sensitive to orientation of cell
1725  * \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.
1726  * \param [out] commonCells
1727  * \param [out] commonCellsI
1728  * \return the correspondance array old to new in a newly allocated array.
1729  * 
1730  */
1731 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1732 {
1733   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1734   getReverseNodalConnectivity(revNodal,revNodalI);
1735   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1736 }
1737
1738 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1739                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1740 {
1741   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1742   int nbOfCells=nodalI->getNumberOfTuples()-1;
1743   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1744   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1745   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1746   std::vector<bool> isFetched(nbOfCells,false);
1747   if(startCellId==0)
1748     {
1749       for(int i=0;i<nbOfCells;i++)
1750         {
1751           if(!isFetched[i])
1752             {
1753               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1754               std::vector<int> v,v2;
1755               if(connOfNode!=connPtr+connIPtr[i+1])
1756                 {
1757                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1758                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1759                   connOfNode++;
1760                 }
1761               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1762                 if(*connOfNode>=0)
1763                   {
1764                     v=v2;
1765                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1766                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1767                     v2.resize(std::distance(v2.begin(),it));
1768                   }
1769               if(v2.size()>1)
1770                 {
1771                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1772                     {
1773                       int pos=commonCellsI->back();
1774                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1775                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1776                         isFetched[*it]=true;
1777                     }
1778                 }
1779             }
1780         }
1781     }
1782   else
1783     {
1784       for(int i=startCellId;i<nbOfCells;i++)
1785         {
1786           if(!isFetched[i])
1787             {
1788               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1789               std::vector<int> v,v2;
1790               if(connOfNode!=connPtr+connIPtr[i+1])
1791                 {
1792                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1793                   connOfNode++;
1794                 }
1795               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1796                 if(*connOfNode>=0)
1797                   {
1798                     v=v2;
1799                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1800                     v2.resize(std::distance(v2.begin(),it));
1801                   }
1802               if(v2.size()>1)
1803                 {
1804                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1805                     {
1806                       int pos=commonCellsI->back();
1807                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1808                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1809                         isFetched[*it]=true;
1810                     }
1811                 }
1812             }
1813         }
1814     }
1815   commonCellsArr=commonCells.retn();
1816   commonCellsIArr=commonCellsI.retn();
1817 }
1818
1819 /*!
1820  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1821  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1822  * than \a other->getNumberOfCells() in the returned array means that there is no
1823  * corresponding cell in \a this mesh.
1824  * It is expected that \a this and \a other meshes share the same node coordinates
1825  * array, if it is not so an exception is thrown. 
1826  *  \param [in] other - the mesh to compare with.
1827  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1828  *         valid values [0,1,2], see zipConnectivityTraducer().
1829  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1830  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1831  *         values. The caller is to delete this array using
1832  *         decrRef() as it is no more needed.
1833  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1834  *         mesh.
1835  *
1836  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1837  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1838  *  \sa checkDeepEquivalOnSameNodesWith()
1839  *  \sa checkGeoEquivalWith()
1840  */
1841 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1842 {
1843   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1844   int nbOfCells=getNumberOfCells();
1845   static const int possibleCompType[]={0,1,2};
1846   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1847     {
1848       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1849       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1850       oss << " !";
1851       throw INTERP_KERNEL::Exception(oss.str().c_str());
1852     }
1853   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1854   arr=o2n->substr(nbOfCells);
1855   arr->setName(other->getName());
1856   int tmp;
1857   if(other->getNumberOfCells()==0)
1858     return true;
1859   return arr->getMaxValue(tmp)<nbOfCells;
1860 }
1861
1862 /*!
1863  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1864  * This method tries to determine if \b other is fully included in \b this.
1865  * The main difference is that this method is not expected to throw exception.
1866  * This method has two outputs :
1867  *
1868  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1869  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1870  */
1871 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1872 {
1873   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1874   DataArrayInt *commonCells=0,*commonCellsI=0;
1875   int thisNbCells=getNumberOfCells();
1876   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1878   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1879   int otherNbCells=other->getNumberOfCells();
1880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1881   arr2->alloc(otherNbCells,1);
1882   arr2->fillWithZero();
1883   int *arr2Ptr=arr2->getPointer();
1884   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1885   for(int i=0;i<nbOfCommon;i++)
1886     {
1887       int start=commonCellsPtr[commonCellsIPtr[i]];
1888       if(start<thisNbCells)
1889         {
1890           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1891             {
1892               int sig=commonCellsPtr[j]>0?1:-1;
1893               int val=std::abs(commonCellsPtr[j])-1;
1894               if(val>=thisNbCells)
1895                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1896             }
1897         }
1898     }
1899   arr2->setName(other->getName());
1900   if(arr2->presenceOfValue(0))
1901     return false;
1902   arr=arr2.retn();
1903   return true;
1904 }
1905
1906 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1907 {
1908   if(!other)
1909     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1910   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1911   if(!otherC)
1912     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1913   std::vector<const MEDCouplingUMesh *> ms(2);
1914   ms[0]=this;
1915   ms[1]=otherC;
1916   return MergeUMeshesOnSameCoords(ms);
1917 }
1918
1919 /*!
1920  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1921  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1922  * cellIds is not given explicitely but by a range python like.
1923  * 
1924  * \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.
1925  * \return a newly allocated
1926  * 
1927  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1928  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1929  */
1930 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1931 {
1932   if(getMeshDimension()!=-1)
1933     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1934   else
1935     {
1936       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1937       if(newNbOfCells!=1)
1938         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1939       if(start!=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  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1948  * The result mesh shares or not the node coordinates array with \a this mesh depending
1949  * on \a keepCoords parameter.
1950  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1951  *           to write this mesh to the MED file, its cells must be sorted using
1952  *           sortCellsInMEDFileFrmt().
1953  *  \param [in] begin - an array of cell ids to include to the new mesh.
1954  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1955  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1956  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1957  *         by calling zipCoords().
1958  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1959  *         to delete this mesh using decrRef() as it is no more needed. 
1960  *  \throw If the coordinates array is not set.
1961  *  \throw If the nodal connectivity of cells is not defined.
1962  *  \throw If any cell id in the array \a begin is not valid.
1963  *
1964  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1965  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1966  */
1967 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1968 {
1969   if(getMeshDimension()!=-1)
1970     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1971   else
1972     {
1973       if(end-begin!=1)
1974         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1975       if(begin[0]!=0)
1976         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1977       incrRef();
1978       return const_cast<MEDCouplingUMesh *>(this);
1979     }
1980 }
1981
1982 /*!
1983  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1984  *
1985  * 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.
1986  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1987  * The number of cells of \b this will remain the same with this method.
1988  *
1989  * \param [in] begin begin of cell ids (included) of cells in this to assign
1990  * \param [in] end end of cell ids (excluded) of cells in this to assign
1991  * \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 ).
1992  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1993  */
1994 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1995 {
1996   checkConnectivityFullyDefined();
1997   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1998   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1999     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2000   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2001     {
2002       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2003       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2004       throw INTERP_KERNEL::Exception(oss.str().c_str());
2005     }
2006   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2007   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2008     {
2009       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2010       throw INTERP_KERNEL::Exception(oss.str().c_str());
2011     }
2012   int nbOfCells=getNumberOfCells();
2013   bool easyAssign=true;
2014   const int *connI=_nodal_connec_index->getConstPointer();
2015   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2016   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2017     {
2018       if(*it>=0 && *it<nbOfCells)
2019         {
2020           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2021         }
2022       else
2023         {
2024           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2025           throw INTERP_KERNEL::Exception(oss.str().c_str());
2026         }
2027     }
2028   if(easyAssign)
2029     {
2030       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2031       computeTypes();
2032     }
2033   else
2034     {
2035       DataArrayInt *arrOut=0,*arrIOut=0;
2036       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2037                                                arrOut,arrIOut);
2038       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2039       setConnectivity(arrOut,arrIOut,true);
2040     }
2041 }
2042
2043 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2044 {
2045   checkConnectivityFullyDefined();
2046   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2047   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2048     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2049   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2050     {
2051       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2052       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2053       throw INTERP_KERNEL::Exception(oss.str().c_str());
2054     }
2055   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2056   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2057     {
2058       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2059       throw INTERP_KERNEL::Exception(oss.str().c_str());
2060     }
2061   int nbOfCells=getNumberOfCells();
2062   bool easyAssign=true;
2063   const int *connI=_nodal_connec_index->getConstPointer();
2064   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2065   int it=start;
2066   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2067     {
2068       if(it>=0 && it<nbOfCells)
2069         {
2070           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2071         }
2072       else
2073         {
2074           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2075           throw INTERP_KERNEL::Exception(oss.str().c_str());
2076         }
2077     }
2078   if(easyAssign)
2079     {
2080       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2081       computeTypes();
2082     }
2083   else
2084     {
2085       DataArrayInt *arrOut=0,*arrIOut=0;
2086       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2087                                                 arrOut,arrIOut);
2088       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2089       setConnectivity(arrOut,arrIOut,true);
2090     }
2091 }                      
2092
2093 /*!
2094  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2095  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2096  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2097  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2098  *
2099  * \param [in] begin input start of array of node ids.
2100  * \param [in] end input end of array of node ids.
2101  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2102  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2103  */
2104 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2105 {
2106   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2107   checkConnectivityFullyDefined();
2108   int tmp=-1;
2109   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2110   std::vector<bool> fastFinder(sz,false);
2111   for(const int *work=begin;work!=end;work++)
2112     if(*work>=0 && *work<sz)
2113       fastFinder[*work]=true;
2114   int nbOfCells=getNumberOfCells();
2115   const int *conn=getNodalConnectivity()->getConstPointer();
2116   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2117   for(int i=0;i<nbOfCells;i++)
2118     {
2119       int ref=0,nbOfHit=0;
2120       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2121         if(*work2>=0)
2122           {
2123             ref++;
2124             if(fastFinder[*work2])
2125               nbOfHit++;
2126           }
2127       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2128         cellIdsKept->pushBackSilent(i);
2129     }
2130   cellIdsKeptArr=cellIdsKept.retn();
2131 }
2132
2133 /*!
2134  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2135  * this->getMeshDimension(), that bound some cells of \a this mesh.
2136  * The cells of lower dimension to include to the result mesh are selected basing on
2137  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2138  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2139  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2140  * created mesh shares the node coordinates array with \a this mesh. 
2141  *  \param [in] begin - the array of node ids.
2142  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2143  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2144  *         array \a begin are added, else cells whose any node is in the
2145  *         array \a begin are added.
2146  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2147  *         to delete this mesh using decrRef() as it is no more needed. 
2148  *  \throw If the coordinates array is not set.
2149  *  \throw If the nodal connectivity of cells is not defined.
2150  *  \throw If any node id in \a begin is not valid.
2151  *
2152  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2153  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2154  */
2155 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2156 {
2157   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2158   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2159   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2160   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2161   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2162 }
2163
2164 /*!
2165  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2166  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2167  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2168  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2169  *         by calling zipCoords().
2170  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2171  *         to delete this mesh using decrRef() as it is no more needed. 
2172  *  \throw If the coordinates array is not set.
2173  *  \throw If the nodal connectivity of cells is not defined.
2174  *
2175  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2176  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2177  */
2178 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2179 {
2180   DataArrayInt *desc=DataArrayInt::New();
2181   DataArrayInt *descIndx=DataArrayInt::New();
2182   DataArrayInt *revDesc=DataArrayInt::New();
2183   DataArrayInt *revDescIndx=DataArrayInt::New();
2184   //
2185   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2186   revDesc->decrRef();
2187   desc->decrRef();
2188   descIndx->decrRef();
2189   int nbOfCells=meshDM1->getNumberOfCells();
2190   const int *revDescIndxC=revDescIndx->getConstPointer();
2191   std::vector<int> boundaryCells;
2192   for(int i=0;i<nbOfCells;i++)
2193     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2194       boundaryCells.push_back(i);
2195   revDescIndx->decrRef();
2196   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2197   return ret;
2198 }
2199
2200 /*!
2201  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2202  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2203  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2204  */
2205 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2206 {
2207   checkFullyDefined();
2208   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2210   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2212   //
2213   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2214   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2215   //
2216   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2217   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2218   const int *revDescPtr=revDesc->getConstPointer();
2219   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2220   int nbOfCells=getNumberOfCells();
2221   std::vector<bool> ret1(nbOfCells,false);
2222   int sz=0;
2223   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2224     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2225       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2226   //
2227   DataArrayInt *ret2=DataArrayInt::New();
2228   ret2->alloc(sz,1);
2229   int *ret2Ptr=ret2->getPointer();
2230   sz=0;
2231   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2232     if(*it)
2233       *ret2Ptr++=sz;
2234   ret2->setName("BoundaryCells");
2235   return ret2;
2236 }
2237
2238 /*!
2239  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2240  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2241  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2242  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2243  *
2244  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2245  * This method method returns cells ids set s = s1 + s2 where :
2246  * 
2247  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2248  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2249  *
2250  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2251  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2252  *
2253  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2254  * \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
2255  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2256  */
2257 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2258 {
2259   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2260     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2261   checkConnectivityFullyDefined();
2262   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2263   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2264     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2267   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2269   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2270   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2271   DataArrayInt *idsOtherInConsti=0;
2272   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2274   if(!b)
2275     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2276   std::set<int> s1;
2277   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2278     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2281   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2282   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2283   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2284   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2285   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2286   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2287   neighThisPartAuto=0;
2288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2289   const int li[2]={0,1};
2290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2291   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2292   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2293   s_renum1->sort();
2294   //
2295   cellIdsRk0=s0arr.retn();
2296   cellIdsRk1=s_renum1.retn();
2297 }
2298
2299 /*!
2300  * 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
2301  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2302  * 
2303  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2304  */
2305 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2306 {
2307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2311   //
2312   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2313   revDesc=0; desc=0; descIndx=0;
2314   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2315   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2316   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2317 }
2318
2319 /*!
2320  * Finds nodes lying on the boundary of \a this mesh.
2321  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2322  *          nodes. The caller is to delete this array using decrRef() as it is no
2323  *          more needed.
2324  *  \throw If the coordinates array is not set.
2325  *  \throw If the nodal connectivity of cells is node defined.
2326  *
2327  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2328  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2329  */
2330 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2331 {
2332   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2333   return skin->computeFetchedNodeIds();
2334 }
2335
2336 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2337 {
2338   incrRef();
2339   return const_cast<MEDCouplingUMesh *>(this);
2340 }
2341
2342 /*!
2343  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2344  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2345  * 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.
2346  * 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.
2347  * 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.
2348  *
2349  * \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
2350  *             parameter is altered during the call.
2351  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2352  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2353  * \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.
2354  *
2355  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2356  */
2357 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2358                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2359 {
2360   checkFullyDefined();
2361   otherDimM1OnSameCoords.checkFullyDefined();
2362   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2363     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2364   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2365     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2366   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2367   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2370   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2371   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2375   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2376   //
2377   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2379   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2380   DataArrayInt *idsTmp=0;
2381   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2382   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2383   if(!b)
2384     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2385   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2386   DataArrayInt *tmp0=0,*tmp1=0;
2387   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2392   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2393   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2394   //
2395   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2396   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2397   nodeIdsToDuplicate=s3.retn();
2398 }
2399
2400 /*!
2401  * This method operates a modification of the connectivity and coords in \b this.
2402  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2403  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2404  * 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
2405  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2406  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2407  * 
2408  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2409  * 
2410  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2411  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2412  */
2413 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2414 {
2415   int nbOfNodes=getNumberOfNodes();
2416   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2417   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2418 }
2419
2420 /*!
2421  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2422  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2423  * This method is a generalization of shiftNodeNumbersInConn().
2424  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2425  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2426  *         this->getNumberOfNodes(), in "Old to New" mode. 
2427  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2428  *  \throw If the nodal connectivity of cells is not defined.
2429  *
2430  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2431  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2432  */
2433 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2434 {
2435   checkConnectivityFullyDefined();
2436   int *conn=getNodalConnectivity()->getPointer();
2437   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2438   int nbOfCells=getNumberOfCells();
2439   for(int i=0;i<nbOfCells;i++)
2440     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2441       {
2442         int& node=conn[iconn];
2443         if(node>=0)//avoid polyhedron separator
2444           {
2445             node=newNodeNumbersO2N[node];
2446           }
2447       }
2448   _nodal_connec->declareAsNew();
2449   updateTime();
2450 }
2451
2452 /*!
2453  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2454  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2455  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2456  * 
2457  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2458  */
2459 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2460 {
2461   checkConnectivityFullyDefined();
2462   int *conn=getNodalConnectivity()->getPointer();
2463   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2464   int nbOfCells=getNumberOfCells();
2465   for(int i=0;i<nbOfCells;i++)
2466     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2467       {
2468         int& node=conn[iconn];
2469         if(node>=0)//avoid polyhedron separator
2470           {
2471             node+=delta;
2472           }
2473       }
2474   _nodal_connec->declareAsNew();
2475   updateTime();
2476 }
2477
2478 /*!
2479  * This method operates a modification of the connectivity in \b this.
2480  * 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.
2481  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2482  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2483  * 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
2484  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2485  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2486  * 
2487  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2488  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2489  * 
2490  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2491  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2492  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2493  */
2494 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2495 {
2496   checkConnectivityFullyDefined();
2497   std::map<int,int> m;
2498   int val=offset;
2499   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2500     m[*work]=val;
2501   int *conn=getNodalConnectivity()->getPointer();
2502   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2503   int nbOfCells=getNumberOfCells();
2504   for(int i=0;i<nbOfCells;i++)
2505     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2506       {
2507         int& node=conn[iconn];
2508         if(node>=0)//avoid polyhedron separator
2509           {
2510             std::map<int,int>::iterator it=m.find(node);
2511             if(it!=m.end())
2512               node=(*it).second;
2513           }
2514       }
2515   updateTime();
2516 }
2517
2518 /*!
2519  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2520  *
2521  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2522  * After the call of this method the number of cells remains the same as before.
2523  *
2524  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2525  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2526  * be strictly in [0;this->getNumberOfCells()).
2527  *
2528  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2529  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2530  * should be contained in[0;this->getNumberOfCells()).
2531  * 
2532  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2533  */
2534 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2535 {
2536   checkConnectivityFullyDefined();
2537   int nbCells=getNumberOfCells();
2538   const int *array=old2NewBg;
2539   if(check)
2540     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2541   //
2542   const int *conn=_nodal_connec->getConstPointer();
2543   const int *connI=_nodal_connec_index->getConstPointer();
2544   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2545   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2546   const int *n2oPtr=n2o->begin();
2547   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2548   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2549   newConn->copyStringInfoFrom(*_nodal_connec);
2550   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2551   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2552   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2553   //
2554   int *newC=newConn->getPointer();
2555   int *newCI=newConnI->getPointer();
2556   int loc=0;
2557   newCI[0]=loc;
2558   for(int i=0;i<nbCells;i++)
2559     {
2560       int pos=n2oPtr[i];
2561       int nbOfElts=connI[pos+1]-connI[pos];
2562       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2563       loc+=nbOfElts;
2564       newCI[i+1]=loc;
2565     }
2566   //
2567   setConnectivity(newConn,newConnI);
2568   if(check)
2569     free(const_cast<int *>(array));
2570 }
2571
2572 /*!
2573  * Finds cells whose bounding boxes intersect a given bounding box.
2574  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2575  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2576  *         zMax (if in 3D). 
2577  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2578  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2579  *         extent of the bounding box of cell to produce an addition to this bounding box.
2580  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2581  *         cells. The caller is to delete this array using decrRef() as it is no more
2582  *         needed. 
2583  *  \throw If the coordinates array is not set.
2584  *  \throw If the nodal connectivity of cells is not defined.
2585  *
2586  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2587  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2588  */
2589 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2590 {
2591   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2592   if(getMeshDimension()==-1)
2593     {
2594       elems->pushBackSilent(0);
2595       return elems.retn();
2596     }
2597   int dim=getSpaceDimension();
2598   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2599   const int* conn      = getNodalConnectivity()->getConstPointer();
2600   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2601   const double* coords = getCoords()->getConstPointer();
2602   int nbOfCells=getNumberOfCells();
2603   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2604     {
2605       for (int i=0; i<dim; i++)
2606         {
2607           elem_bb[i*2]=std::numeric_limits<double>::max();
2608           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2609         }
2610
2611       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2612         {
2613           int node= conn[inode];
2614           if(node>=0)//avoid polyhedron separator
2615             {
2616               for (int idim=0; idim<dim; idim++)
2617                 {
2618                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2619                     {
2620                       elem_bb[idim*2] = coords[node*dim+idim] ;
2621                     }
2622                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2623                     {
2624                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2625                     }
2626                 }
2627             }
2628         }
2629       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2630         elems->pushBackSilent(ielem);
2631     }
2632   return elems.retn();
2633 }
2634
2635 /*!
2636  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2637  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2638  * added in 'elems' parameter.
2639  */
2640 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2641 {
2642   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2643   if(getMeshDimension()==-1)
2644     {
2645       elems->pushBackSilent(0);
2646       return elems.retn();
2647     }
2648   int dim=getSpaceDimension();
2649   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2650   const int* conn      = getNodalConnectivity()->getConstPointer();
2651   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2652   const double* coords = getCoords()->getConstPointer();
2653   int nbOfCells=getNumberOfCells();
2654   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2655     {
2656       for (int i=0; i<dim; i++)
2657         {
2658           elem_bb[i*2]=std::numeric_limits<double>::max();
2659           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2660         }
2661
2662       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2663         {
2664           int node= conn[inode];
2665           if(node>=0)//avoid polyhedron separator
2666             {
2667               for (int idim=0; idim<dim; idim++)
2668                 {
2669                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2670                     {
2671                       elem_bb[idim*2] = coords[node*dim+idim] ;
2672                     }
2673                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2674                     {
2675                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2676                     }
2677                 }
2678             }
2679         }
2680       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2681         elems->pushBackSilent(ielem);
2682     }
2683   return elems.retn();
2684 }
2685
2686 /*!
2687  * Returns a type of a cell by its id.
2688  *  \param [in] cellId - the id of the cell of interest.
2689  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2690  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2691  */
2692 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2693 {
2694   const int *ptI=_nodal_connec_index->getConstPointer();
2695   const int *pt=_nodal_connec->getConstPointer();
2696   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2697     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2698   else
2699     {
2700       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2701       throw INTERP_KERNEL::Exception(oss.str().c_str());
2702     }
2703 }
2704
2705 /*!
2706  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2707  * This method does not throw exception if geometric type \a type is not in \a this.
2708  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2709  * The coordinates array is not considered here.
2710  *
2711  * \param [in] type the geometric type
2712  * \return cell ids in this having geometric type \a type.
2713  */
2714 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2715 {
2716   
2717   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2718   ret->alloc(0,1);
2719   checkConnectivityFullyDefined();
2720   int nbCells=getNumberOfCells();
2721   int mdim=getMeshDimension();
2722   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2723   if(mdim!=(int)cm.getDimension())
2724     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2725   const int *ptI=_nodal_connec_index->getConstPointer();
2726   const int *pt=_nodal_connec->getConstPointer();
2727   for(int i=0;i<nbCells;i++)
2728     {
2729       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2730         ret->pushBackSilent(i);
2731     }
2732   return ret.retn();
2733 }
2734
2735 /*!
2736  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2737  */
2738 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2739 {
2740   const int *ptI=_nodal_connec_index->getConstPointer();
2741   const int *pt=_nodal_connec->getConstPointer();
2742   int nbOfCells=getNumberOfCells();
2743   int ret=0;
2744   for(int i=0;i<nbOfCells;i++)
2745     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2746       ret++;
2747   return ret;
2748 }
2749
2750 /*!
2751  * Returns the nodal connectivity of a given cell.
2752  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2753  * all returned node ids can be used in getCoordinatesOfNode().
2754  *  \param [in] cellId - an id of the cell of interest.
2755  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2756  *         cleared before the appending.
2757  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2758  */
2759 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2760 {
2761   const int *ptI=_nodal_connec_index->getConstPointer();
2762   const int *pt=_nodal_connec->getConstPointer();
2763   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2764     if(*w>=0)
2765       conn.push_back(*w);
2766 }
2767
2768 std::string MEDCouplingUMesh::simpleRepr() const
2769 {
2770   static const char msg0[]="No coordinates specified !";
2771   std::ostringstream ret;
2772   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2773   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2774   int tmpp1,tmpp2;
2775   double tt=getTime(tmpp1,tmpp2);
2776   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2777   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2778   if(_mesh_dim>=-1)
2779     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2780   else
2781     { ret << " Mesh dimension has not been set or is invalid !"; }
2782   if(_coords!=0)
2783     {
2784       const int spaceDim=getSpaceDimension();
2785       ret << spaceDim << "\nInfo attached on space dimension : ";
2786       for(int i=0;i<spaceDim;i++)
2787         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2788       ret << "\n";
2789     }
2790   else
2791     ret << msg0 << "\n";
2792   ret << "Number of nodes : ";
2793   if(_coords!=0)
2794     ret << getNumberOfNodes() << "\n";
2795   else
2796     ret << msg0 << "\n";
2797   ret << "Number of cells : ";
2798   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2799     ret << getNumberOfCells() << "\n";
2800   else
2801     ret << "No connectivity specified !" << "\n";
2802   ret << "Cell types present : ";
2803   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2804     {
2805       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2806       ret << cm.getRepr() << " ";
2807     }
2808   ret << "\n";
2809   return ret.str();
2810 }
2811
2812 std::string MEDCouplingUMesh::advancedRepr() const
2813 {
2814   std::ostringstream ret;
2815   ret << simpleRepr();
2816   ret << "\nCoordinates array : \n___________________\n\n";
2817   if(_coords)
2818     _coords->reprWithoutNameStream(ret);
2819   else
2820     ret << "No array set !\n";
2821   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2822   reprConnectivityOfThisLL(ret);
2823   return ret.str();
2824 }
2825
2826 /*!
2827  * This method returns a C++ code that is a dump of \a this.
2828  * This method will throw if this is not fully defined.
2829  */
2830 std::string MEDCouplingUMesh::cppRepr() const
2831 {
2832   static const char coordsName[]="coords";
2833   static const char connName[]="conn";
2834   static const char connIName[]="connI";
2835   checkFullyDefined();
2836   std::ostringstream ret; ret << "// coordinates" << std::endl;
2837   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2838   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2839   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2840   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2841   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2842   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2843   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2844   return ret.str();
2845 }
2846
2847 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2848 {
2849   std::ostringstream ret;
2850   reprConnectivityOfThisLL(ret);
2851   return ret.str();
2852 }
2853
2854 /*!
2855  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2856  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2857  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2858  * some algos).
2859  * 
2860  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2861  * 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
2862  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2863  */
2864 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2865 {
2866   int mdim=getMeshDimension();
2867   if(mdim<0)
2868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2869   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2870   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2871   bool needToCpyCT=true;
2872   if(!_nodal_connec)
2873     {
2874       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2875       needToCpyCT=false;
2876     }
2877   else
2878     {
2879       tmp1=_nodal_connec;
2880       tmp1->incrRef();
2881     }
2882   if(!_nodal_connec_index)
2883     {
2884       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2885       needToCpyCT=false;
2886     }
2887   else
2888     {
2889       tmp2=_nodal_connec_index;
2890       tmp2->incrRef();
2891     }
2892   ret->setConnectivity(tmp1,tmp2,false);
2893   if(needToCpyCT)
2894     ret->_types=_types;
2895   if(!_coords)
2896     {
2897       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2898       ret->setCoords(coords);
2899     }
2900   else
2901     ret->setCoords(_coords);
2902   return ret.retn();
2903 }
2904
2905 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2906 {
2907   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2908     {
2909       int nbOfCells=getNumberOfCells();
2910       const int *c=_nodal_connec->getConstPointer();
2911       const int *ci=_nodal_connec_index->getConstPointer();
2912       for(int i=0;i<nbOfCells;i++)
2913         {
2914           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2915           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2916           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2917           stream << "\n";
2918         }
2919     }
2920   else
2921     stream << "Connectivity not defined !\n";
2922 }
2923
2924 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2925 {
2926   const int *ptI=_nodal_connec_index->getConstPointer();
2927   const int *pt=_nodal_connec->getConstPointer();
2928   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2929     return ptI[cellId+1]-ptI[cellId]-1;
2930   else
2931     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2932 }
2933
2934 /*!
2935  * Returns types of cells of the specified part of \a this mesh.
2936  * This method avoids computing sub-mesh explicitely to get its types.
2937  *  \param [in] begin - an array of cell ids of interest.
2938  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2939  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2940  *         describing the cell types. 
2941  *  \throw If the coordinates array is not set.
2942  *  \throw If the nodal connectivity of cells is not defined.
2943  *  \sa getAllGeoTypes()
2944  */
2945 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2946 {
2947   checkFullyDefined();
2948   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2949   const int *conn=_nodal_connec->getConstPointer();
2950   const int *connIndex=_nodal_connec_index->getConstPointer();
2951   for(const int *w=begin;w!=end;w++)
2952     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2953   return ret;
2954 }
2955
2956 /*!
2957  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2958  * a set of types of cells constituting \a this mesh. 
2959  * This method is for advanced users having prepared their connectivity before. For
2960  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2961  *  \param [in] conn - the nodal connectivity array. 
2962  *  \param [in] connIndex - the nodal connectivity index array.
2963  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2964  *         mesh is updated.
2965  */
2966 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2967 {
2968   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2969   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2970   if(isComputingTypes)
2971     computeTypes();
2972   declareAsNew();
2973 }
2974
2975 /*!
2976  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2977  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2978  */
2979 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2980                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2981                                                                                 _types(other._types)
2982 {
2983   if(other._nodal_connec)
2984     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2985   if(other._nodal_connec_index)
2986     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2987 }
2988
2989 MEDCouplingUMesh::~MEDCouplingUMesh()
2990 {
2991   if(_nodal_connec)
2992     _nodal_connec->decrRef();
2993   if(_nodal_connec_index)
2994     _nodal_connec_index->decrRef();
2995 }
2996
2997 /*!
2998  * Recomputes a set of cell types of \a this mesh. For more info see
2999  * \ref MEDCouplingUMeshNodalConnectivity.
3000  */
3001 void MEDCouplingUMesh::computeTypes()
3002 {
3003   if(_nodal_connec && _nodal_connec_index)
3004     {
3005       _types.clear();
3006       const int *conn=_nodal_connec->getConstPointer();
3007       const int *connIndex=_nodal_connec_index->getConstPointer();
3008       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3009       if (nbOfElem > 0)
3010         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3011           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3012     }
3013 }
3014
3015 /*!
3016  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3017  */
3018 void MEDCouplingUMesh::checkFullyDefined() const
3019 {
3020   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3021     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3022 }
3023
3024 /*!
3025  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3026  */
3027 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3028 {
3029   if(!_nodal_connec_index || !_nodal_connec)
3030     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3031 }
3032
3033 /*!
3034  * Returns a number of cells constituting \a this mesh. 
3035  *  \return int - the number of cells in \a this mesh.
3036  *  \throw If the nodal connectivity of cells is not defined.
3037  */
3038 int MEDCouplingUMesh::getNumberOfCells() const
3039
3040   if(_nodal_connec_index)
3041     return _nodal_connec_index->getNumberOfTuples()-1;
3042   else
3043     if(_mesh_dim==-1)
3044       return 1;
3045     else
3046       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3047 }
3048
3049 /*!
3050  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3051  * mesh. For more info see \ref MEDCouplingMeshesPage.
3052  *  \return int - the dimension of \a this mesh.
3053  *  \throw If the mesh dimension is not defined using setMeshDimension().
3054  */
3055 int MEDCouplingUMesh::getMeshDimension() const
3056 {
3057   if(_mesh_dim<-1)
3058     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3059   return _mesh_dim;
3060 }
3061
3062 /*!
3063  * Returns a length of the nodal connectivity array.
3064  * This method is for test reason. Normally the integer returned is not useable by
3065  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3066  *  \return int - the length of the nodal connectivity array.
3067  */
3068 int MEDCouplingUMesh::getMeshLength() const
3069 {
3070   return _nodal_connec->getNbOfElems();
3071 }
3072
3073 /*!
3074  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3075  */
3076 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3077 {
3078   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3079   tinyInfo.push_back(getMeshDimension());
3080   tinyInfo.push_back(getNumberOfCells());
3081   if(_nodal_connec)
3082     tinyInfo.push_back(getMeshLength());
3083   else
3084     tinyInfo.push_back(-1);
3085 }
3086
3087 /*!
3088  * First step of unserialization process.
3089  */
3090 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3091 {
3092   return tinyInfo[6]<=0;
3093 }
3094
3095 /*!
3096  * Second step of serialization process.
3097  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3098  */
3099 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3100 {
3101   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3102   if(tinyInfo[5]!=-1)
3103     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3104 }
3105
3106 /*!
3107  * Third and final step of serialization process.
3108  */
3109 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3110 {
3111   MEDCouplingPointSet::serialize(a1,a2);
3112   if(getMeshDimension()>-1)
3113     {
3114       a1=DataArrayInt::New();
3115       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3116       int *ptA1=a1->getPointer();
3117       const int *conn=getNodalConnectivity()->getConstPointer();
3118       const int *index=getNodalConnectivityIndex()->getConstPointer();
3119       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3120       std::copy(conn,conn+getMeshLength(),ptA1);
3121     }
3122   else
3123     a1=0;
3124 }
3125
3126 /*!
3127  * Second and final unserialization process.
3128  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3129  */
3130 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3131 {
3132   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3133   setMeshDimension(tinyInfo[5]);
3134   if(tinyInfo[7]!=-1)
3135     {
3136       // Connectivity
3137       const int *recvBuffer=a1->getConstPointer();
3138       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3139       myConnecIndex->alloc(tinyInfo[6]+1,1);
3140       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3141       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3142       myConnec->alloc(tinyInfo[7],1);
3143       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3144       setConnectivity(myConnec, myConnecIndex);
3145     }
3146 }
3147
3148 /*!
3149  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3150  * CellIds are given using range specified by a start an end and step.
3151  */
3152 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3153 {
3154   checkFullyDefined();
3155   int ncell=getNumberOfCells();
3156   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3157   ret->_mesh_dim=_mesh_dim;
3158   ret->setCoords(_coords);
3159   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3160   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3161   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3162   int work=start;
3163   const int *conn=_nodal_connec->getConstPointer();
3164   const int *connIndex=_nodal_connec_index->getConstPointer();
3165   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3166     {
3167       if(work>=0 && work<ncell)
3168         {
3169           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3170         }
3171       else
3172         {
3173           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3174           throw INTERP_KERNEL::Exception(oss.str().c_str());
3175         }
3176     }
3177   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3178   int *newConnPtr=newConn->getPointer();
3179   std::set<INTERP_KERNEL::NormalizedCellType> types;
3180   work=start;
3181   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3182     {
3183       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3184       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3185     }
3186   ret->setConnectivity(newConn,newConnI,false);
3187   ret->_types=types;
3188   ret->copyTinyInfoFrom(this);
3189   return ret.retn();
3190 }
3191
3192 /*!
3193  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3194  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3195  * The return newly allocated mesh will share the same coordinates as \a this.
3196  */
3197 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3198 {
3199   checkConnectivityFullyDefined();
3200   int ncell=getNumberOfCells();
3201   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3202   ret->_mesh_dim=_mesh_dim;
3203   ret->setCoords(_coords);
3204   std::size_t nbOfElemsRet=std::distance(begin,end);
3205   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3206   connIndexRet[0]=0;
3207   const int *conn=_nodal_connec->getConstPointer();
3208   const int *connIndex=_nodal_connec_index->getConstPointer();
3209   int newNbring=0;
3210   for(const int *work=begin;work!=end;work++,newNbring++)
3211     {
3212       if(*work>=0 && *work<ncell)
3213         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3214       else
3215         {
3216           free(connIndexRet);
3217           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3218           throw INTERP_KERNEL::Exception(oss.str().c_str());
3219         }
3220     }
3221   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3222   int *connRetWork=connRet;
3223   std::set<INTERP_KERNEL::NormalizedCellType> types;
3224   for(const int *work=begin;work!=end;work++)
3225     {
3226       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3227       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3228     }
3229   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3230   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3231   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3232   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3233   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3234   ret->_types=types;
3235   ret->copyTinyInfoFrom(this);
3236   return ret.retn();
3237 }
3238
3239 /*!
3240  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3241  * mesh.<br>
3242  * For 1D cells, the returned field contains lengths.<br>
3243  * For 2D cells, the returned field contains areas.<br>
3244  * For 3D cells, the returned field contains volumes.
3245  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3246  *         orientation, i.e. the volume is always positive.
3247  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3248  *         and one time . The caller is to delete this field using decrRef() as it is no
3249  *         more needed.
3250  */
3251 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3252 {
3253   std::string name="MeasureOfMesh_";
3254   name+=getName();
3255   int nbelem=getNumberOfCells();
3256   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3257   field->setName(name);
3258   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3259   array->alloc(nbelem,1);
3260   double *area_vol=array->getPointer();
3261   field->setArray(array) ; array=0;
3262   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3263   field->synchronizeTimeWithMesh();
3264   if(getMeshDimension()!=-1)
3265     {
3266       int ipt;
3267       INTERP_KERNEL::NormalizedCellType type;
3268       int dim_space=getSpaceDimension();
3269       const double *coords=getCoords()->getConstPointer();
3270       const int *connec=getNodalConnectivity()->getConstPointer();
3271       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3272       for(int iel=0;iel<nbelem;iel++)
3273         {
3274           ipt=connec_index[iel];
3275           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3276           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);
3277         }
3278       if(isAbs)
3279         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3280     }
3281   else
3282     {
3283       area_vol[0]=std::numeric_limits<double>::max();
3284     }
3285   return field.retn();
3286 }
3287
3288 /*!
3289  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3290  * mesh.<br>
3291  * For 1D cells, the returned array contains lengths.<br>
3292  * For 2D cells, the returned array contains areas.<br>
3293  * For 3D cells, the returned array contains volumes.
3294  * This method avoids building explicitly a part of \a this mesh to perform the work.
3295  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3296  *         orientation, i.e. the volume is always positive.
3297  *  \param [in] begin - an array of cell ids of interest.
3298  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3299  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3300  *          delete this array using decrRef() as it is no more needed.
3301  * 
3302  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3303  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3304  *  \sa getMeasureField()
3305  */
3306 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3307 {
3308   std::string name="PartMeasureOfMesh_";
3309   name+=getName();
3310   int nbelem=(int)std::distance(begin,end);
3311   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3312   array->setName(name);
3313   array->alloc(nbelem,1);
3314   double *area_vol=array->getPointer();
3315   if(getMeshDimension()!=-1)
3316     {
3317       int ipt;
3318       INTERP_KERNEL::NormalizedCellType type;
3319       int dim_space=getSpaceDimension();
3320       const double *coords=getCoords()->getConstPointer();
3321       const int *connec=getNodalConnectivity()->getConstPointer();
3322       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3323       for(const int *iel=begin;iel!=end;iel++)
3324         {
3325           ipt=connec_index[*iel];
3326           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3327           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3328         }
3329       if(isAbs)
3330         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3331     }
3332   else
3333     {
3334       area_vol[0]=std::numeric_limits<double>::max();
3335     }
3336   return array.retn();
3337 }
3338
3339 /*!
3340  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3341  * \a this one. The returned field contains the dual cell volume for each corresponding
3342  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3343  *  the dual mesh in P1 sens of \a this.<br>
3344  * For 1D cells, the returned field contains lengths.<br>
3345  * For 2D cells, the returned field contains areas.<br>
3346  * For 3D cells, the returned field contains volumes.
3347  * This method is useful to check "P1*" conservative interpolators.
3348  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3349  *         orientation, i.e. the volume is always positive.
3350  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3351  *          nodes and one time. The caller is to delete this array using decrRef() as
3352  *          it is no more needed.
3353  */
3354 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3355 {
3356   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3357   std::string name="MeasureOnNodeOfMesh_";
3358   name+=getName();
3359   int nbNodes=getNumberOfNodes();
3360   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3361   double cst=1./((double)getMeshDimension()+1.);
3362   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3363   array->alloc(nbNodes,1);
3364   double *valsToFill=array->getPointer();
3365   std::fill(valsToFill,valsToFill+nbNodes,0.);
3366   const double *values=tmp->getArray()->getConstPointer();
3367   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3369   getReverseNodalConnectivity(da,daInd);
3370   const int *daPtr=da->getConstPointer();
3371   const int *daIPtr=daInd->getConstPointer();
3372   for(int i=0;i<nbNodes;i++)
3373     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3374       valsToFill[i]+=cst*values[*cell];
3375   ret->setMesh(this);
3376   ret->setArray(array);
3377   return ret.retn();
3378 }
3379
3380 /*!
3381  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3382  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3383  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3384  * and are normalized.
3385  * <br> \a this can be either 
3386  * - a  2D mesh in 2D or 3D space or 
3387  * - an 1D mesh in 2D space.
3388  * 
3389  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3390  *          cells and one time. The caller is to delete this field using decrRef() as
3391  *          it is no more needed.
3392  *  \throw If the nodal connectivity of cells is not defined.
3393  *  \throw If the coordinates array is not set.
3394  *  \throw If the mesh dimension is not set.
3395  *  \throw If the mesh and space dimension is not as specified above.
3396  */
3397 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3398 {
3399   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3400     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3402   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3403   int nbOfCells=getNumberOfCells();
3404   int nbComp=getMeshDimension()+1;
3405   array->alloc(nbOfCells,nbComp);
3406   double *vals=array->getPointer();
3407   const int *connI=_nodal_connec_index->getConstPointer();
3408   const int *conn=_nodal_connec->getConstPointer();
3409   const double *coords=_coords->getConstPointer();
3410   if(getMeshDimension()==2)
3411     {
3412       if(getSpaceDimension()==3)
3413         {
3414           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3415           const double *locPtr=loc->getConstPointer();
3416           for(int i=0;i<nbOfCells;i++,vals+=3)
3417             {
3418               int offset=connI[i];
3419               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3420               double n=INTERP_KERNEL::norm<3>(vals);
3421               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3422             }
3423         }
3424       else
3425         {
3426           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3427           const double *isAbsPtr=isAbs->getArray()->begin();
3428           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3429             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3430         }
3431     }
3432   else//meshdimension==1
3433     {
3434       double tmp[2];
3435       for(int i=0;i<nbOfCells;i++)
3436         {
3437           int offset=connI[i];
3438           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3439           double n=INTERP_KERNEL::norm<2>(tmp);
3440           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3441           *vals++=-tmp[1];
3442           *vals++=tmp[0];
3443         }
3444     }
3445   ret->setArray(array);
3446   ret->setMesh(this);
3447   ret->synchronizeTimeWithSupport();
3448   return ret.retn();
3449 }
3450
3451 /*!
3452  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3453  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3454  * and are normalized.
3455  * <br> \a this can be either 
3456  * - a  2D mesh in 2D or 3D space or 
3457  * - an 1D mesh in 2D space.
3458  * 
3459  * This method avoids building explicitly a part of \a this mesh to perform the work.
3460  *  \param [in] begin - an array of cell ids of interest.
3461  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3462  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3463  *          cells and one time. The caller is to delete this field using decrRef() as
3464  *          it is no more needed.
3465  *  \throw If the nodal connectivity of cells is not defined.
3466  *  \throw If the coordinates array is not set.
3467  *  \throw If the mesh dimension is not set.
3468  *  \throw If the mesh and space dimension is not as specified above.
3469  *  \sa buildOrthogonalField()
3470  *
3471  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3472  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3473  */
3474 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3475 {
3476   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3477     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3478   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3479   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3480   std::size_t nbelems=std::distance(begin,end);
3481   int nbComp=getMeshDimension()+1;
3482   array->alloc((int)nbelems,nbComp);
3483   double *vals=array->getPointer();
3484   const int *connI=_nodal_connec_index->getConstPointer();
3485   const int *conn=_nodal_connec->getConstPointer();
3486   const double *coords=_coords->getConstPointer();
3487   if(getMeshDimension()==2)
3488     {
3489       if(getSpaceDimension()==3)
3490         {
3491           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3492           const double *locPtr=loc->getConstPointer();
3493           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3494             {
3495               int offset=connI[*i];
3496               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3497               double n=INTERP_KERNEL::norm<3>(vals);
3498               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3499             }
3500         }
3501       else
3502         {
3503           for(std::size_t i=0;i<nbelems;i++)
3504             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3505         }
3506     }
3507   else//meshdimension==1
3508     {
3509       double tmp[2];
3510       for(const int *i=begin;i!=end;i++)
3511         {
3512           int offset=connI[*i];
3513           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3514           double n=INTERP_KERNEL::norm<2>(tmp);
3515           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3516           *vals++=-tmp[1];
3517           *vals++=tmp[0];
3518         }
3519     }
3520   ret->setArray(array);
3521   ret->setMesh(this);
3522   ret->synchronizeTimeWithSupport();
3523   return ret.retn();
3524 }
3525
3526 /*!
3527  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3528  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3529  * and are \b not normalized.
3530  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3531  *          cells and one time. The caller is to delete this field using decrRef() as
3532  *          it is no more needed.
3533  *  \throw If the nodal connectivity of cells is not defined.
3534  *  \throw If the coordinates array is not set.
3535  *  \throw If \a this->getMeshDimension() != 1.
3536  *  \throw If \a this mesh includes cells of type other than SEG2.
3537  */
3538 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3539 {
3540    if(getMeshDimension()!=1)
3541     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3542    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3543      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3544    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3545    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3546    int nbOfCells=getNumberOfCells();
3547    int spaceDim=getSpaceDimension();
3548    array->alloc(nbOfCells,spaceDim);
3549    double *pt=array->getPointer();
3550    const double *coo=getCoords()->getConstPointer();
3551    std::vector<int> conn;
3552    conn.reserve(2);
3553    for(int i=0;i<nbOfCells;i++)
3554      {
3555        conn.resize(0);
3556        getNodeIdsOfCell(i,conn);
3557        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3558      }
3559    ret->setArray(array);
3560    ret->setMesh(this);
3561    ret->synchronizeTimeWithSupport();
3562    return ret.retn();   
3563 }
3564
3565 /*!
3566  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3567  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3568  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3569  * from. If a result face is shared by two 3D cells, then the face in included twice in
3570  * the result mesh.
3571  *  \param [in] origin - 3 components of a point defining location of the plane.
3572  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3573  *         must be greater than 1e-6.
3574  *  \param [in] eps - half-thickness of the plane.
3575  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3576  *         producing correspondent 2D cells. The caller is to delete this array
3577  *         using decrRef() as it is no more needed.
3578  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3579  *         not share the node coordinates array with \a this mesh. The caller is to
3580  *         delete this mesh using decrRef() as it is no more needed.  
3581  *  \throw If the coordinates array is not set.
3582  *  \throw If the nodal connectivity of cells is not defined.
3583  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3584  *  \throw If magnitude of \a vec is less than 1e-6.
3585  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3586  *  \throw If \a this includes quadratic cells.
3587  */
3588 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3589 {
3590   checkFullyDefined();
3591   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3592     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3593   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3594   if(candidates->empty())
3595     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3596   std::vector<int> nodes;
3597   DataArrayInt *cellIds1D=0;
3598   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3599   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3600   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3601   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3602   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3603   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3604   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3605   revDesc2=0; revDescIndx2=0;
3606   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3607   revDesc1=0; revDescIndx1=0;
3608   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3609   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3610   //
3611   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3612   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3613     cut3DCurve[*it]=-1;
3614   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3615   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3616   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3617                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3618                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3619   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3620   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3621   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3622   if(cellIds2->empty())
3623     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3624   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3625   ret->setCoords(mDesc1->getCoords());
3626   ret->setConnectivity(conn,connI,true);
3627   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3628   return ret.retn();
3629 }
3630
3631 /*!
3632  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3633 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
3634 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3635 the result mesh.
3636  *  \param [in] origin - 3 components of a point defining location of the plane.
3637  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3638  *         must be greater than 1e-6.
3639  *  \param [in] eps - half-thickness of the plane.
3640  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3641  *         producing correspondent segments. The caller is to delete this array
3642  *         using decrRef() as it is no more needed.
3643  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3644  *         mesh in 3D space. This mesh does not share the node coordinates array with
3645  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3646  *         no more needed. 
3647  *  \throw If the coordinates array is not set.
3648  *  \throw If the nodal connectivity of cells is not defined.
3649  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3650  *  \throw If magnitude of \a vec is less than 1e-6.
3651  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3652  *  \throw If \a this includes quadratic cells.
3653  */
3654 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3655 {
3656   checkFullyDefined();
3657   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3658     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3659   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3660   if(candidates->empty())
3661     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3662   std::vector<int> nodes;
3663   DataArrayInt *cellIds1D=0;
3664   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3665   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3666   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3667   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3669   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3670   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3671   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3672   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3673   //
3674   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3675   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3676     cut3DCurve[*it]=-1;
3677   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3678   int ncellsSub=subMesh->getNumberOfCells();
3679   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3680   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3681                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3682                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3683   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3684   conn->alloc(0,1);
3685   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3686   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3687   for(int i=0;i<ncellsSub;i++)
3688     {
3689       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3690         {
3691           if(cut3DSurf[i].first!=-2)
3692             {
3693               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3694               connI->pushBackSilent(conn->getNumberOfTuples());
3695               cellIds2->pushBackSilent(i);
3696             }
3697           else
3698             {
3699               int cellId3DSurf=cut3DSurf[i].second;
3700               int offset=nodalI[cellId3DSurf]+1;
3701               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3702               for(int j=0;j<nbOfEdges;j++)
3703                 {
3704                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3705                   connI->pushBackSilent(conn->getNumberOfTuples());
3706                   cellIds2->pushBackSilent(cellId3DSurf);
3707                 }
3708             }
3709         }
3710     }
3711   if(cellIds2->empty())
3712     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3713   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3714   ret->setCoords(mDesc1->getCoords());
3715   ret->setConnectivity(conn,connI,true);
3716   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3717   return ret.retn();
3718 }
3719
3720 /*!
3721  * Finds cells whose bounding boxes intersect a given plane.
3722  *  \param [in] origin - 3 components of a point defining location of the plane.
3723  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3724  *         must be greater than 1e-6.
3725  *  \param [in] eps - half-thickness of the plane.
3726  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3727  *         cells. The caller is to delete this array using decrRef() as it is no more
3728  *         needed.
3729  *  \throw If the coordinates array is not set.
3730  *  \throw If the nodal connectivity of cells is not defined.
3731  *  \throw If \a this->getSpaceDimension() != 3.
3732  *  \throw If magnitude of \a vec is less than 1e-6.
3733  *  \sa buildSlice3D()
3734  */
3735 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3736 {
3737   checkFullyDefined();
3738   if(getSpaceDimension()!=3)
3739     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3740   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3741   if(normm<1e-6)
3742     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3743   double vec2[3];
3744   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3745   double angle=acos(vec[2]/normm);
3746   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3747   double bbox[6];
3748   if(angle>eps)
3749     {
3750       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3751       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3752       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3753       mw->setCoords(coo);
3754       mw->getBoundingBox(bbox);
3755       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3756       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3757     }
3758   else
3759     {
3760       getBoundingBox(bbox);
3761       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3762       cellIds=getCellsInBoundingBox(bbox,eps);
3763     }
3764   return cellIds.retn();
3765 }
3766
3767 /*!
3768  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3769  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3770  * No consideration of coordinate is done by this method.
3771  * 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)
3772  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3773  */
3774 bool MEDCouplingUMesh::isContiguous1D() const
3775 {
3776   if(getMeshDimension()!=1)
3777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3778   int nbCells=getNumberOfCells();
3779   if(nbCells<1)
3780     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3781   const int *connI=_nodal_connec_index->getConstPointer();
3782   const int *conn=_nodal_connec->getConstPointer();
3783   int ref=conn[connI[0]+2];
3784   for(int i=1;i<nbCells;i++)
3785     {
3786       if(conn[connI[i]+1]!=ref)
3787         return false;
3788       ref=conn[connI[i]+2];
3789     }
3790   return true;
3791 }
3792
3793 /*!
3794  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3795  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3796  * \param pt reference point of the line
3797  * \param v normalized director vector of the line
3798  * \param eps max precision before throwing an exception
3799  * \param res output of size this->getNumberOfCells
3800  */
3801 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3802 {
3803   if(getMeshDimension()!=1)
3804     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3805    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3806      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3807    if(getSpaceDimension()!=3)
3808      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3809    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3810    const double *fPtr=f->getArray()->getConstPointer();
3811    double tmp[3];
3812    for(int i=0;i<getNumberOfCells();i++)
3813      {
3814        const double *tmp1=fPtr+3*i;
3815        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3816        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3817        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3818        double n1=INTERP_KERNEL::norm<3>(tmp);
3819        n1/=INTERP_KERNEL::norm<3>(tmp1);
3820        if(n1>eps)
3821          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3822      }
3823    const double *coo=getCoords()->getConstPointer();
3824    for(int i=0;i<getNumberOfNodes();i++)
3825      {
3826        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3827        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3828        res[i]=std::accumulate(tmp,tmp+3,0.);
3829      }
3830 }
3831
3832 /*!
3833  * 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. 
3834  * \a this is expected to be a mesh so that its space dimension is equal to its
3835  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3836  * 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).
3837  
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  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3843  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3844  *
3845  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3846  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3847  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3848  * \return the positive value of the distance.
3849  * \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
3850  * dimension - 1.
3851  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3852  */
3853 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3854 {
3855   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3856   if(meshDim!=spaceDim-1)
3857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3858   if(meshDim!=2 && meshDim!=1)
3859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3860   checkFullyDefined();
3861   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3862     { 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()); }
3863   DataArrayInt *ret1=0;
3864   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3865   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3866   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3867   cellId=*ret1Safe->begin();
3868   return *ret0->begin();
3869 }
3870
3871 /*!
3872  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3873  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3874  * 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
3875  * 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).
3876  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3877  * 
3878  * \a this is expected to be a mesh so that its space dimension is equal to its
3879  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3880  * 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).
3881  *
3882  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3883  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3884  *
3885  * \param [in] pts the list of points in which each tuple represents a point
3886  * \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.
3887  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3888  * \throw if number of components of \a pts is not equal to the space dimension.
3889  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3890  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3891  */
3892 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3893 {
3894   if(!pts)
3895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3896   pts->checkAllocated();
3897   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3898   if(meshDim!=spaceDim-1)
3899     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3900   if(meshDim!=2 && meshDim!=1)
3901     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3902   if(pts->getNumberOfComponents()!=spaceDim)
3903     {
3904       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3905       throw INTERP_KERNEL::Exception(oss.str().c_str());
3906     }
3907   checkFullyDefined();
3908   int nbCells=getNumberOfCells();
3909   if(nbCells==0)
3910     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3911   int nbOfPts=pts->getNumberOfTuples();
3912   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3913   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3914   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3915   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3916   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3917   const double *bbox(bboxArr->begin());
3918   switch(spaceDim)
3919     {
3920     case 3:
3921       {
3922         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3923         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3924           {
3925             double x=std::numeric_limits<double>::max();
3926             std::vector<int> elems;
3927             myTree.getMinDistanceOfMax(ptsPtr,x);
3928             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3929             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3930           }
3931         break;
3932       }
3933     case 2:
3934       {
3935         BBTreeDst<2> myTree(bbox,0,0,nbCells);
3936         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3937           {
3938             double x=std::numeric_limits<double>::max();
3939             std::vector<int> elems;
3940             myTree.getMinDistanceOfMax(ptsPtr,x);
3941             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3942             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3943           }
3944         break;
3945       }
3946     default:
3947       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3948     }
3949   cellIds=ret1.retn();
3950   return ret0.retn();
3951 }
3952
3953 /*!
3954  * \param [in] pt the start pointer (included) of the coordinates of the point
3955  * \param [in] cellIdsBg the start pointer (included) of cellIds
3956  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3957  * \param [in] nc nodal connectivity
3958  * \param [in] ncI nodal connectivity index
3959  * \param [in,out] ret0 the min distance between \a this and the external input point
3960  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3961  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3962  */
3963 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)
3964 {
3965   cellId=-1;
3966   ret0=std::numeric_limits<double>::max();
3967   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3968     {
3969       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3970         {
3971         case INTERP_KERNEL::NORM_TRI3:
3972           {
3973             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3974             if(tmp<ret0)
3975               { ret0=tmp; cellId=*zeCell; }
3976             break;
3977           }
3978         case INTERP_KERNEL::NORM_QUAD4:
3979         case INTERP_KERNEL::NORM_POLYGON:
3980           {
3981             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3982             if(tmp<ret0)
3983               { ret0=tmp; cellId=*zeCell; }
3984             break;
3985           }
3986         default:
3987           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3988         }
3989     }
3990 }
3991
3992 /*!
3993  * \param [in] pt the start pointer (included) of the coordinates of the point
3994  * \param [in] cellIdsBg the start pointer (included) of cellIds
3995  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3996  * \param [in] nc nodal connectivity
3997  * \param [in] ncI nodal connectivity index
3998  * \param [in,out] ret0 the min distance between \a this and the external input point
3999  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4000  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4001  */
4002 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)
4003 {
4004   cellId=-1;
4005   ret0=std::numeric_limits<double>::max();
4006   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4007     {
4008        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4009         {
4010         case INTERP_KERNEL::NORM_SEG2:
4011           {
4012             std::size_t uselessEntry=0;
4013             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4014             tmp=sqrt(tmp);
4015             if(tmp<ret0)
4016               { ret0=tmp; cellId=*zeCell; }
4017             break;
4018           }
4019         default:
4020           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4021         }
4022     }
4023 }
4024
4025 /*!
4026  * Finds cells in contact with a ball (i.e. a point with precision). 
4027  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4028  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4029  *
4030  * \warning This method is suitable if the caller intends to evaluate only one
4031  *          point, for more points getCellsContainingPoints() is recommended as it is
4032  *          faster. 
4033  *  \param [in] pos - array of coordinates of the ball central point.
4034  *  \param [in] eps - ball radius.
4035  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4036  *         if there are no such cells.
4037  *  \throw If the coordinates array is not set.
4038  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4039  */
4040 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4041 {
4042   std::vector<int> elts;
4043   getCellsContainingPoint(pos,eps,elts);
4044   if(elts.empty())
4045     return -1;
4046   return elts.front();
4047 }
4048
4049 /*!
4050  * Finds cells in contact with a ball (i.e. a point with precision).
4051  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4052  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4053  * \warning This method is suitable if the caller intends to evaluate only one
4054  *          point, for more points getCellsContainingPoints() is recommended as it is
4055  *          faster. 
4056  *  \param [in] pos - array of coordinates of the ball central point.
4057  *  \param [in] eps - ball radius.
4058  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4059  *         before inserting ids.
4060  *  \throw If the coordinates array is not set.
4061  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4062  *
4063  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4064  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4065  */
4066 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4067 {
4068   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4069   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4070   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4071 }
4072
4073 /// @cond INTERNAL
4074
4075 namespace ParaMEDMEM
4076 {
4077   template<const int SPACEDIMM>
4078   class DummyClsMCUG
4079   {
4080   public:
4081     static const int MY_SPACEDIM=SPACEDIMM;
4082     static const int MY_MESHDIM=8;
4083     typedef int MyConnType;
4084     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4085     // begin
4086     // useless, but for windows compilation ...
4087     const double* getCoordinatesPtr() const { return 0; }
4088     const int* getConnectivityPtr() const { return 0; }
4089     const int* getConnectivityIndexPtr() const { return 0; }
4090     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4091     // end
4092   };
4093   
4094   /*!
4095    * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4096    */
4097   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map<INTERP_KERNEL::Node *,int>& m)
4098   {
4099     INTERP_KERNEL::Edge *ret=0;
4100     INTERP_KERNEL::Node *n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),*n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4101     m[n0]=bg[0]; m[n1]=bg[1];
4102     switch(typ)
4103       {
4104       case INTERP_KERNEL::NORM_SEG2:
4105         {
4106           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4107           break;
4108         }
4109       case INTERP_KERNEL::NORM_SEG3:
4110         {
4111           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4112           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4113           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4114           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4115           bool colinearity(inters.areColinears());
4116           delete e1; delete e2;
4117           if(colinearity)
4118             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4119           else
4120             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4121           break;
4122         }
4123       default:
4124         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4125       } 
4126     return ret;
4127   }
4128
4129   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4130   {
4131     INTERP_KERNEL::Edge *ret=0;
4132     switch(typ)
4133       {
4134       case INTERP_KERNEL::NORM_SEG2:
4135         {
4136           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4137           break;
4138         }
4139       case INTERP_KERNEL::NORM_SEG3:
4140         {
4141           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4142           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4143           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4144           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4145           bool colinearity=inters.areColinears();
4146           delete e1; delete e2;
4147           if(colinearity)
4148             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4149           else
4150             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4151           mapp2[bg[2]].second=false;
4152           break;
4153         }
4154       default:
4155         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4156       }
4157     return ret;
4158   }
4159
4160   /*!
4161    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4162    * the global mesh 'mDesc'.
4163    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4164    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4165    */
4166   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4167       std::map<INTERP_KERNEL::Node *,int>& mapp)
4168       throw(INTERP_KERNEL::Exception)
4169   {
4170     mapp.clear();
4171     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.
4172     const double *coo=mDesc->getCoords()->getConstPointer();
4173     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4174     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4175     std::set<int> s;
4176     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4177       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4178     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4179       {
4180         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4181         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4182       }
4183     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4184     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4185       {
4186         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4187         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4188       }
4189     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4190       {
4191         if((*it2).second.second)
4192           mapp[(*it2).second.first]=(*it2).first;
4193         ((*it2).second.first)->decrRef();
4194       }
4195     return ret;
4196   }
4197
4198   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4199   {
4200     if(nodeId>=offset2)
4201       {
4202         int locId=nodeId-offset2;
4203         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4204       }
4205     if(nodeId>=offset1)
4206       {
4207         int locId=nodeId-offset1;
4208         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4209       }
4210     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4211   }
4212
4213   /**
4214    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4215    */
4216   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4217                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4218                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4219   {
4220     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4221       {
4222         int eltId1=abs(*desc1)-1;
4223         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4224           {
4225             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4226             if(it==mappRev.end())
4227               {
4228                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4229                 mapp[node]=*it1;
4230                 mappRev[*it1]=node;
4231               }
4232           }
4233       }
4234   }
4235 }
4236
4237 /// @endcond
4238
4239 template<int SPACEDIM>
4240 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4241                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4242 {
4243   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4244   int *eltsIndexPtr(eltsIndex->getPointer());
4245   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4246   const double *bbox(bboxArr->begin());
4247   int nbOfCells=getNumberOfCells();
4248   const int *conn=_nodal_connec->getConstPointer();
4249   const int *connI=_nodal_connec_index->getConstPointer();
4250   double bb[2*SPACEDIM];
4251   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4252   for(int i=0;i<nbOfPoints;i++)
4253     {
4254       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4255       for(int j=0;j<SPACEDIM;j++)
4256         {
4257           bb[2*j]=pos[SPACEDIM*i+j];
4258           bb[2*j+1]=pos[SPACEDIM*i+j];
4259         }
4260       std::vector<int> candidates;
4261       myTree.getIntersectingElems(bb,candidates);
4262       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4263         {
4264           int sz(connI[(*iter)+1]-connI[*iter]-1);
4265           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4266           bool status(false);
4267           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4268             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4269           else
4270             {
4271               if(SPACEDIM!=2)
4272                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4273               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4274               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4275               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4276               INTERP_KERNEL::QuadraticPolygon *pol(0);
4277               for(int j=0;j<sz;j++)
4278                 {
4279                   int nodeId(conn[connI[*iter]+1+j]);
4280                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4281                 }
4282               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4283                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4284               else
4285                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4286               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4287               double a(0.),b(0.),c(0.);
4288               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4289               status=pol->isInOrOut2(n);
4290               delete pol; n->decrRef();
4291             }
4292           if(status)
4293             {
4294               eltsIndexPtr[i+1]++;
4295               elts->pushBackSilent(*iter);
4296             }
4297         }
4298     }
4299 }
4300 /*!
4301  * Finds cells in contact with several balls (i.e. points with precision).
4302  * This method is an extension of getCellContainingPoint() and
4303  * getCellsContainingPoint() for the case of multiple points.
4304  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4305  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4306  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4307  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4308  *         this->getSpaceDimension() * \a nbOfPoints 
4309  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4310  *  \param [in] eps - radius of balls (i.e. the precision).
4311  *  \param [out] elts - vector returning ids of found cells.
4312  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4313  *         dividing cell ids in \a elts into groups each referring to one
4314  *         point. Its every element (except the last one) is an index pointing to the
4315  *         first id of a group of cells. For example cells in contact with the *i*-th
4316  *         point are described by following range of indices:
4317  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4318  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4319  *         Number of cells in contact with the *i*-th point is
4320  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4321  *  \throw If the coordinates array is not set.
4322  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4323  *
4324  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4325  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4326  */
4327 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4328                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4329 {
4330   int spaceDim=getSpaceDimension();
4331   int mDim=getMeshDimension();
4332   if(spaceDim==3)
4333     {
4334       if(mDim==3)
4335         {
4336           const double *coords=_coords->getConstPointer();
4337           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4338         }
4339       /*else if(mDim==2)
4340         {
4341           
4342         }*/
4343       else
4344         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4345     }
4346   else if(spaceDim==2)
4347     {
4348       if(mDim==2)
4349         {
4350           const double *coords=_coords->getConstPointer();
4351           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4352         }
4353       else
4354         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4355     }
4356   else if(spaceDim==1)
4357     {
4358       if(mDim==1)
4359         {
4360           const double *coords=_coords->getConstPointer();
4361           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4362         }
4363       else
4364         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4365     }
4366   else
4367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4368 }
4369
4370 /*!
4371  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4372  * least two its edges intersect each other anywhere except their extremities. An
4373  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4374  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4375  *         cleared before filling in.
4376  *  \param [in] eps - precision.
4377  *  \throw If \a this->getMeshDimension() != 2.
4378  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4379  */
4380 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4381 {
4382   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4383   if(getMeshDimension()!=2)
4384     throw INTERP_KERNEL::Exception(msg);
4385   int spaceDim=getSpaceDimension();
4386   if(spaceDim!=2 && spaceDim!=3)
4387     throw INTERP_KERNEL::Exception(msg);
4388   const int *conn=_nodal_connec->getConstPointer();
4389   const int *connI=_nodal_connec_index->getConstPointer();
4390   int nbOfCells=getNumberOfCells();
4391   std::vector<double> cell2DinS2;
4392   for(int i=0;i<nbOfCells;i++)
4393     {
4394       int offset=connI[i];
4395       int nbOfNodesForCell=connI[i+1]-offset-1;
4396       if(nbOfNodesForCell<=3)
4397         continue;
4398       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4399       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4400       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4401         cells.push_back(i);
4402       cell2DinS2.clear();
4403     }
4404 }
4405
4406 /*!
4407  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4408  *
4409  * 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.
4410  * 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.
4411  * 
4412  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4413  * This convex envelop is computed using Jarvis march algorithm.
4414  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4415  * 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)
4416  * 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.
4417  *
4418  * \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.
4419  */
4420 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4421 {
4422   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4423     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4424   checkFullyDefined();
4425   const double *coords=getCoords()->getConstPointer();
4426   int nbOfCells=getNumberOfCells();
4427   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4428   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4429   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4430   int *workIndexOut=nodalConnecIndexOut->getPointer();
4431   *workIndexOut=0;
4432   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4433   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4434   std::set<INTERP_KERNEL::NormalizedCellType> types;
4435   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4436   isChanged->alloc(0,1);
4437   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4438     {
4439       int pos=nodalConnecOut->getNumberOfTuples();
4440       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4441         isChanged->pushBackSilent(i);
4442       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4443       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4444     }
4445   if(isChanged->empty())
4446     return 0;
4447   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4448   _types=types;
4449   return isChanged.retn();
4450 }
4451
4452 /*!
4453  * This method is \b NOT const because it can modify \a this.
4454  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4455  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4456  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4457  * \b 1 for translation and rotation around point of 'mesh1D'.
4458  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4459  */
4460 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4461 {
4462   checkFullyDefined();
4463   mesh1D->checkFullyDefined();
4464   if(!mesh1D->isContiguous1D())
4465     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4466   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4467     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4468   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4469     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4470   if(mesh1D->getMeshDimension()!=1)
4471     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4472   bool isQuad=false;
4473   if(isPresenceOfQuadratic())
4474     {
4475       if(mesh1D->isFullyQuadratic())
4476         isQuad=true;
4477       else
4478         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4479     }
4480   zipCoords();
4481   int oldNbOfNodes=getNumberOfNodes();
4482   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4483   switch(policy)
4484     {
4485     case 0:
4486       {
4487         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4488         break;
4489       }
4490     case 1:
4491       {
4492         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4493         break;
4494       }
4495     default:
4496       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4497     }
4498   setCoords(newCoords);
4499   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4500   updateTime();
4501   return ret.retn();
4502 }
4503
4504 /*!
4505  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4506  * If it is not the case an exception will be thrown.
4507  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4508  * intersection of plane defined by ('origin','vec').
4509  * This method has one in/out parameter : 'cut3DCurve'.
4510  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4511  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4512  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4513  * This method will throw an exception if \a this contains a non linear segment.
4514  */
4515 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4516 {
4517   checkFullyDefined();
4518   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4519     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4520   int ncells=getNumberOfCells();
4521   int nnodes=getNumberOfNodes();
4522   double vec2[3],vec3[3],vec4[3];
4523   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4524   if(normm<1e-6)
4525     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4526   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4527   const int *conn=_nodal_connec->getConstPointer();
4528   const int *connI=_nodal_connec_index->getConstPointer();
4529   const double *coo=_coords->getConstPointer();
4530   std::vector<double> addCoo;
4531   for(int i=0;i<ncells;i++)
4532     {
4533       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4534         {
4535           if(cut3DCurve[i]==-2)
4536             {
4537               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4538               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];
4539               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4540               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4541               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4542                 {
4543                   const double *st2=coo+3*st;
4544                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4545                   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]));
4546                   if(pos>eps && pos<1-eps)
4547                     {
4548                       int nNode=((int)addCoo.size())/3;
4549                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4550                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4551                       cut3DCurve[i]=nnodes+nNode;
4552                     }
4553                 }
4554             }
4555         }
4556       else
4557         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4558     }
4559   if(!addCoo.empty())
4560     {
4561       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4562       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4563       coo2->alloc(newNbOfNodes,3);
4564       double *tmp=coo2->getPointer();
4565       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4566       std::copy(addCoo.begin(),addCoo.end(),tmp);
4567       DataArrayDouble::SetArrayIn(coo2,_coords);
4568     }
4569 }
4570
4571 /*!
4572  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4573  * \param mesh1D is the input 1D mesh used for translation computation.
4574  * \return newCoords new coords filled by this method. 
4575  */
4576 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4577 {
4578   int oldNbOfNodes=getNumberOfNodes();
4579   int nbOf1DCells=mesh1D->getNumberOfCells();
4580   int spaceDim=getSpaceDimension();
4581   DataArrayDouble *ret=DataArrayDouble::New();
4582   std::vector<bool> isQuads;
4583   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4584   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4585   double *retPtr=ret->getPointer();
4586   const double *coords=getCoords()->getConstPointer();
4587   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4588   std::vector<int> v;
4589   std::vector<double> c;
4590   double vec[3];
4591   v.reserve(3);
4592   c.reserve(6);
4593   for(int i=0;i<nbOf1DCells;i++)
4594     {
4595       v.resize(0);
4596       mesh1D->getNodeIdsOfCell(i,v);
4597       c.resize(0);
4598       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4599       mesh1D->getCoordinatesOfNode(v[0],c);
4600       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4601       for(int j=0;j<oldNbOfNodes;j++)
4602         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4603       if(isQuad)
4604         {
4605           c.resize(0);
4606           mesh1D->getCoordinatesOfNode(v[1],c);
4607           mesh1D->getCoordinatesOfNode(v[0],c);
4608           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4609           for(int j=0;j<oldNbOfNodes;j++)
4610             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4611         }
4612     }
4613   ret->copyStringInfoFrom(*getCoords());
4614   return ret;
4615 }
4616
4617 /*!
4618  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4619  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4620  * \return newCoords new coords filled by this method. 
4621  */
4622 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4623 {
4624   if(mesh1D->getSpaceDimension()==2)
4625     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4626   if(mesh1D->getSpaceDimension()==3)
4627     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4628   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4629 }
4630
4631 /*!
4632  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4633  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4634  * \return newCoords new coords filled by this method. 
4635  */
4636 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4637 {
4638   if(isQuad)
4639     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4640   int oldNbOfNodes=getNumberOfNodes();
4641   int nbOf1DCells=mesh1D->getNumberOfCells();
4642   if(nbOf1DCells<2)
4643     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4644   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4645   int nbOfLevsInVec=nbOf1DCells+1;
4646   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4647   double *retPtr=ret->getPointer();
4648   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4649   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4650   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4651   tmp->setCoords(tmp2);
4652   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4653   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4654   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4655   for(int i=1;i<nbOfLevsInVec;i++)
4656     {
4657       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4658       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4659       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4660       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4661       tmp->translate(vec);
4662       double tmp3[2],radius,alpha,alpha0;
4663       const double *p0=i+1<nbOfLevsInVec?begin:third;
4664       const double *p1=i+1<nbOfLevsInVec?end:begin;
4665       const double *p2=i+1<nbOfLevsInVec?third:end;
4666       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4667       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]);
4668       double angle=acos(cosangle/(radius*radius));
4669       tmp->rotate(end,0,angle);
4670       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4671     }
4672   return ret.retn();
4673 }
4674
4675 /*!
4676  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4677  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4678  * \return newCoords new coords filled by this method. 
4679  */
4680 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4681 {
4682   if(isQuad)
4683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4684   int oldNbOfNodes=getNumberOfNodes();
4685   int nbOf1DCells=mesh1D->getNumberOfCells();
4686   if(nbOf1DCells<2)
4687     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4688   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4689   int nbOfLevsInVec=nbOf1DCells+1;
4690   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4691   double *retPtr=ret->getPointer();
4692   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4693   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4694   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4695   tmp->setCoords(tmp2);
4696   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4697   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4698   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4699   for(int i=1;i<nbOfLevsInVec;i++)
4700     {
4701       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4702       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4703       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4704       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4705       tmp->translate(vec);
4706       double tmp3[2],radius,alpha,alpha0;
4707       const double *p0=i+1<nbOfLevsInVec?begin:third;
4708       const double *p1=i+1<nbOfLevsInVec?end:begin;
4709       const double *p2=i+1<nbOfLevsInVec?third:end;
4710       double vecPlane[3]={
4711         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4712         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4713         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4714       };
4715       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4716       if(norm>1.e-7)
4717         {
4718           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4719           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4720           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4721           double s2=norm2;
4722           double c2=cos(asin(s2));
4723           double m[3][3]={
4724             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4725             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4726             {-vec2[1]*s2, vec2[0]*s2, c2}
4727           };
4728           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]};
4729           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]};
4730           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]};
4731           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4732           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]);
4733           double angle=acos(cosangle/(radius*radius));
4734           tmp->rotate(end,vecPlane,angle);
4735           
4736         }
4737       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4738     }
4739   return ret.retn();
4740 }
4741
4742 /*!
4743  * This method is private because not easy to use for end user. This method is const contrary to
4744  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4745  * the coords sorted slice by slice.
4746  * \param isQuad specifies presence of quadratic cells.
4747  */
4748 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4749 {
4750   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4751   int nbOf2DCells=getNumberOfCells();
4752   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4753   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4754   const int *conn=_nodal_connec->getConstPointer();
4755   const int *connI=_nodal_connec_index->getConstPointer();
4756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4758   newConnI->alloc(nbOf3DCells+1,1);
4759   int *newConnIPtr=newConnI->getPointer();
4760   *newConnIPtr++=0;
4761   std::vector<int> newc;
4762   for(int j=0;j<nbOf2DCells;j++)
4763     {
4764       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4765       *newConnIPtr++=(int)newc.size();
4766     }
4767   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4768   int *newConnPtr=newConn->getPointer();
4769   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4770   newConnIPtr=newConnI->getPointer();
4771   for(int iz=0;iz<nbOf1DCells;iz++)
4772     {
4773       if(iz!=0)
4774         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4775       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4776         {
4777           int icell=(int)(iter-newc.begin());
4778           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4779             {
4780               if(*iter!=-1)
4781                 *newConnPtr=(*iter)+iz*deltaPerLev;
4782               else
4783                 *newConnPtr=-1;
4784             }
4785           else
4786             *newConnPtr=(*iter);
4787         }
4788     }
4789   ret->setConnectivity(newConn,newConnI,true);
4790   ret->setCoords(getCoords());
4791   return ret;
4792 }
4793
4794 /*!
4795  * Checks if \a this mesh is constituted by only quadratic cells.
4796  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4797  *  \throw If the coordinates array is not set.
4798  *  \throw If the nodal connectivity of cells is not defined.
4799  */
4800 bool MEDCouplingUMesh::isFullyQuadratic() const
4801 {
4802   checkFullyDefined();
4803   bool ret=true;
4804   int nbOfCells=getNumberOfCells();
4805   for(int i=0;i<nbOfCells && ret;i++)
4806     {
4807       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4808       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4809       ret=cm.isQuadratic();
4810     }
4811   return ret;
4812 }
4813
4814 /*!
4815  * Checks if \a this mesh includes any quadratic cell.
4816  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4817  *  \throw If the coordinates array is not set.
4818  *  \throw If the nodal connectivity of cells is not defined.
4819  */
4820 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4821 {
4822   checkFullyDefined();
4823   bool ret=false;
4824   int nbOfCells=getNumberOfCells();
4825   for(int i=0;i<nbOfCells && !ret;i++)
4826     {
4827       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4828       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4829       ret=cm.isQuadratic();
4830     }
4831   return ret;
4832 }
4833
4834 /*!
4835  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4836  * this mesh, it remains unchanged.
4837  *  \throw If the coordinates array is not set.
4838  *  \throw If the nodal connectivity of cells is not defined.
4839  */
4840 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4841 {
4842   checkFullyDefined();
4843   int nbOfCells=getNumberOfCells();
4844   int delta=0;
4845   const int *iciptr=_nodal_connec_index->getConstPointer();
4846   for(int i=0;i<nbOfCells;i++)
4847     {
4848       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4849       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4850       if(cm.isQuadratic())
4851         {
4852           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4853           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4854           if(!cml.isDynamic())
4855             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4856           else
4857             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4858         }
4859     }
4860   if(delta==0)
4861     return ;
4862   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4863   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4864   const int *icptr=_nodal_connec->getConstPointer();
4865   newConn->alloc(getMeshLength()-delta,1);
4866   newConnI->alloc(nbOfCells+1,1);
4867   int *ocptr=newConn->getPointer();
4868   int *ociptr=newConnI->getPointer();
4869   *ociptr=0;
4870   _types.clear();
4871   for(int i=0;i<nbOfCells;i++,ociptr++)
4872     {
4873       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4874       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4875       if(!cm.isQuadratic())
4876         {
4877           _types.insert(type);
4878           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4879           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4880         }
4881       else
4882         {
4883           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4884           _types.insert(typel);
4885           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4886           int newNbOfNodes=cml.getNumberOfNodes();
4887           if(cml.isDynamic())
4888             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4889           *ocptr++=(int)typel;
4890           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4891           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4892         }
4893     }
4894   setConnectivity(newConn,newConnI,false);
4895 }
4896
4897 /*!
4898  * This method converts all linear cell in \a this to quadratic one.
4899  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4900  * 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)
4901  * 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.
4902  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4903  * end of the existing coordinates.
4904  * 
4905  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4906  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4907  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4908  * 
4909  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4910  *
4911  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4912  */
4913 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4914 {
4915   DataArrayInt *conn=0,*connI=0;
4916   DataArrayDouble *coords=0;
4917   std::set<INTERP_KERNEL::NormalizedCellType> types;
4918   checkFullyDefined();
4919   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4920   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4921   int meshDim=getMeshDimension();
4922   switch(conversionType)
4923     {
4924     case 0:
4925       switch(meshDim)
4926         {
4927         case 1:
4928           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4929           connSafe=conn; connISafe=connI; coordsSafe=coords;
4930           break;
4931         case 2:
4932           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4933           connSafe=conn; connISafe=connI; coordsSafe=coords;
4934           break;
4935         case 3:
4936           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4937           connSafe=conn; connISafe=connI; coordsSafe=coords;
4938           break;
4939         default:
4940           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4941         }
4942       break;
4943     case 1:
4944       {
4945         switch(meshDim)
4946         {
4947         case 1:
4948           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4949           connSafe=conn; connISafe=connI; coordsSafe=coords;
4950           break;
4951         case 2:
4952           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4953           connSafe=conn; connISafe=connI; coordsSafe=coords;
4954           break;
4955         case 3:
4956           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4957           connSafe=conn; connISafe=connI; coordsSafe=coords;
4958           break;
4959         default:
4960           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4961         }
4962         break;
4963       }
4964     default:
4965       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4966     }
4967   setConnectivity(connSafe,connISafe,false);
4968   _types=types;
4969   setCoords(coordsSafe);
4970   return ret.retn();
4971 }
4972
4973 /*!
4974  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4975  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4976  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4977  */
4978 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4979 {
4980   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4981   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4984   int nbOfCells=getNumberOfCells();
4985   int nbOfNodes=getNumberOfNodes();
4986   const int *cPtr=_nodal_connec->getConstPointer();
4987   const int *icPtr=_nodal_connec_index->getConstPointer();
4988   int lastVal=0,offset=nbOfNodes;
4989   for(int i=0;i<nbOfCells;i++,icPtr++)
4990     {
4991       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4992       if(type==INTERP_KERNEL::NORM_SEG2)
4993         {
4994           types.insert(INTERP_KERNEL::NORM_SEG3);
4995           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4996           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4997           newConn->pushBackSilent(offset++);
4998           lastVal+=4;
4999           newConnI->pushBackSilent(lastVal);
5000           ret->pushBackSilent(i);
5001         }
5002       else
5003         {
5004           types.insert(type);
5005           lastVal+=(icPtr[1]-icPtr[0]);
5006           newConnI->pushBackSilent(lastVal);
5007           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5008         }
5009     }
5010   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5011   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5012   return ret.retn();
5013 }
5014
5015 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
5016 {
5017   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5018   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5019   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5020   //
5021   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5022   DataArrayInt *conn1D=0,*conn1DI=0;
5023   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5024   DataArrayDouble *coordsTmp=0;
5025   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5026   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5027   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5028   const int *c1DPtr=conn1D->begin();
5029   const int *c1DIPtr=conn1DI->begin();
5030   int nbOfCells=getNumberOfCells();
5031   const int *cPtr=_nodal_connec->getConstPointer();
5032   const int *icPtr=_nodal_connec_index->getConstPointer();
5033   int lastVal=0;
5034   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5035     {
5036       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5037       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5038       if(!cm.isQuadratic())
5039         {
5040           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5041           types.insert(typ2); newConn->pushBackSilent(typ2);
5042           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5043           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5044             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5045           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5046           newConnI->pushBackSilent(lastVal);
5047           ret->pushBackSilent(i);
5048         }
5049       else
5050         {
5051           types.insert(typ);
5052           lastVal+=(icPtr[1]-icPtr[0]);
5053           newConnI->pushBackSilent(lastVal);
5054           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5055         }
5056     }
5057   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5058   return ret.retn();
5059 }
5060
5061 /*!
5062  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5063  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5064  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5065  */
5066 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5067 {
5068   
5069   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5070   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5071   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5072 }
5073
5074 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5075 {
5076   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5077   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5078   //
5079   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5080   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5081   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5082   //
5083   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5084   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5085   DataArrayInt *conn1D=0,*conn1DI=0;
5086   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5087   DataArrayDouble *coordsTmp=0;
5088   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5089   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5090   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5091   const int *c1DPtr=conn1D->begin();
5092   const int *c1DIPtr=conn1DI->begin();
5093   int nbOfCells=getNumberOfCells();
5094   const int *cPtr=_nodal_connec->getConstPointer();
5095   const int *icPtr=_nodal_connec_index->getConstPointer();
5096   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5097   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5098     {
5099       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5100       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5101       if(!cm.isQuadratic())
5102         {
5103           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5104           types.insert(typ2); newConn->pushBackSilent(typ2);
5105           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5106           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5107             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5108           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5109           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5110           newConnI->pushBackSilent(lastVal);
5111           ret->pushBackSilent(i);
5112         }
5113       else
5114         {
5115           types.insert(typ);
5116           lastVal+=(icPtr[1]-icPtr[0]);
5117           newConnI->pushBackSilent(lastVal);
5118           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5119         }
5120     }
5121   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5122   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5123   return ret.retn();
5124 }
5125
5126 /*!
5127  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5128  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5129  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5130  */
5131 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5132 {
5133   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5134   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5135   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5136 }
5137
5138 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5139 {
5140   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5141   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5142   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5143   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5144   //
5145   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5146   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5147   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5148   //
5149   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5150   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5151   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5152   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5153   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5154   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5155   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5156   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5157   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5158   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5159   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5160   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5161   int nbOfCells=getNumberOfCells();
5162   const int *cPtr=_nodal_connec->getConstPointer();
5163   const int *icPtr=_nodal_connec_index->getConstPointer();
5164   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5165   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5166     {
5167       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5168       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5169       if(!cm.isQuadratic())
5170         {
5171           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5172           if(typ2==INTERP_KERNEL::NORM_ERROR)
5173             {
5174               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5175               throw INTERP_KERNEL::Exception(oss.str().c_str());
5176             }
5177           types.insert(typ2); newConn->pushBackSilent(typ2);
5178           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5179           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5180             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5181           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5182             {
5183               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5184               int tmpPos=newConn->getNumberOfTuples();
5185               newConn->pushBackSilent(nodeId2);
5186               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5187             }
5188           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5189           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5190           newConnI->pushBackSilent(lastVal);
5191           ret->pushBackSilent(i);
5192         }
5193       else
5194         {
5195           types.insert(typ);
5196           lastVal+=(icPtr[1]-icPtr[0]);
5197           newConnI->pushBackSilent(lastVal);
5198           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5199         }
5200     }
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5202   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5203   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5204   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5205   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5206   int *c=newConn->getPointer();
5207   const int *cI(newConnI->begin());
5208   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5209     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5210   offset=coordsTmp2Safe->getNumberOfTuples();
5211   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5212     c[cI[(*elt)+1]-1]+=offset;
5213   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5214   return ret.retn();
5215 }
5216
5217 /*!
5218  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5219  * so that the number of cells remains the same. Quadratic faces are converted to
5220  * polygons. This method works only for 2D meshes in
5221  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5222  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5223  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5224  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5225  *         a polylinized edge constituting the input polygon.
5226  *  \throw If the coordinates array is not set.
5227  *  \throw If the nodal connectivity of cells is not defined.
5228  *  \throw If \a this->getMeshDimension() != 2.
5229  *  \throw If \a this->getSpaceDimension() != 2.
5230  */
5231 void MEDCouplingUMesh::tessellate2D(double eps)
5232 {
5233   checkFullyDefined();
5234   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5235     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5236   double epsa=fabs(eps);
5237   if(epsa<std::numeric_limits<double>::min())
5238     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 !");
5239   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5240   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5243   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5244   revDesc1=0; revDescIndx1=0;
5245   mDesc->tessellate2DCurve(eps);
5246   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5247   setCoords(mDesc->getCoords());
5248 }
5249
5250 /*!
5251  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5252  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5253  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5254  *         a sub-divided edge.
5255  *  \throw If the coordinates array is not set.
5256  *  \throw If the nodal connectivity of cells is not defined.
5257  *  \throw If \a this->getMeshDimension() != 1.
5258  *  \throw If \a this->getSpaceDimension() != 2.
5259  */
5260 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5261 {
5262   checkFullyDefined();
5263   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5264     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5265   double epsa=fabs(eps);
5266   if(epsa<std::numeric_limits<double>::min())
5267     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 !");
5268   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5269   int nbCells=getNumberOfCells();
5270   int nbNodes=getNumberOfNodes();
5271   const int *conn=_nodal_connec->getConstPointer();
5272   const int *connI=_nodal_connec_index->getConstPointer();
5273   const double *coords=_coords->getConstPointer();
5274   std::vector<double> addCoo;
5275   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5277   newConnI->alloc(nbCells+1,1);
5278   int *newConnIPtr=newConnI->getPointer();
5279   *newConnIPtr=0;
5280   int tmp1[3];
5281   INTERP_KERNEL::Node *tmp2[3];
5282   std::set<INTERP_KERNEL::NormalizedCellType> types;
5283   for(int i=0;i<nbCells;i++,newConnIPtr++)
5284     {
5285       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5286       if(cm.isQuadratic())
5287         {//assert(connI[i+1]-connI[i]-1==3)
5288           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5289           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5290           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5291           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5292           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5293           if(eac)
5294             {
5295               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5296               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5297               delete eac;
5298               newConnIPtr[1]=(int)newConn.size();
5299             }
5300           else
5301             {
5302               types.insert(INTERP_KERNEL::NORM_SEG2);
5303               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5304               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5305               newConnIPtr[1]=newConnIPtr[0]+3;
5306             }
5307         }
5308       else
5309         {
5310           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5311           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5312           newConnIPtr[1]=newConnIPtr[0]+3;
5313         }
5314     }
5315   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5316     return ;
5317   _types=types;
5318   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5320   newConnArr->alloc((int)newConn.size(),1);
5321   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5322   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5323   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5324   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5325   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5326   std::copy(addCoo.begin(),addCoo.end(),work);
5327   DataArrayDouble::SetArrayIn(newCoords,_coords);
5328   updateTime();
5329 }
5330
5331 /*!
5332  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5333  * In addition, returns an array mapping new cells to old ones. <br>
5334  * This method typically increases the number of cells in \a this mesh
5335  * but the number of nodes remains \b unchanged.
5336  * That's why the 3D splitting policies
5337  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5338  *  \param [in] policy - specifies a pattern used for splitting.
5339  * The semantic of \a policy is:
5340  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5341  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5342  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5343  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5344  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5345  *          an id of old cell producing it. The caller is to delete this array using
5346  *         decrRef() as it is no more needed. 
5347  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5348  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5349  *          and \a this->getMeshDimension() != 3. 
5350  *  \throw If \a policy is not one of the four discussed above.
5351  *  \throw If the nodal connectivity of cells is not defined.
5352  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5353  */
5354 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5355 {
5356   switch(policy)
5357     {
5358     case 0:
5359       return simplexizePol0();
5360     case 1:
5361       return simplexizePol1();
5362     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5363       return simplexizePlanarFace5();
5364     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5365       return simplexizePlanarFace6();
5366     default:
5367       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)");
5368     }
5369 }
5370
5371 /*!
5372  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5373  * - 1D: INTERP_KERNEL::NORM_SEG2
5374  * - 2D: INTERP_KERNEL::NORM_TRI3
5375  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5376  *
5377  * This method is useful for users that need to use P1 field services as
5378  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5379  * All these methods need mesh support containing only simplex cells.
5380  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5381  *  \throw If the coordinates array is not set.
5382  *  \throw If the nodal connectivity of cells is not defined.
5383  *  \throw If \a this->getMeshDimension() < 1.
5384  */
5385 bool MEDCouplingUMesh::areOnlySimplexCells() const
5386 {
5387   checkFullyDefined();
5388   int mdim=getMeshDimension();
5389   if(mdim<1 || mdim>3)
5390     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5391   int nbCells=getNumberOfCells();
5392   const int *conn=_nodal_connec->getConstPointer();
5393   const int *connI=_nodal_connec_index->getConstPointer();
5394   for(int i=0;i<nbCells;i++)
5395     {
5396       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5397       if(!cm.isSimplex())
5398         return false;
5399     }
5400   return true;
5401 }
5402
5403 /*!
5404  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5405  */
5406 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5407 {
5408   checkConnectivityFullyDefined();
5409   if(getMeshDimension()!=2)
5410     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5411   int nbOfCells=getNumberOfCells();
5412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5413   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5414   ret->alloc(nbOfCells+nbOfCutCells,1);
5415   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5416   int *retPt=ret->getPointer();
5417   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5419   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5420   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5421   int *pt=newConn->getPointer();
5422   int *ptI=newConnI->getPointer();
5423   ptI[0]=0;
5424   const int *oldc=_nodal_connec->getConstPointer();
5425   const int *ci=_nodal_connec_index->getConstPointer();
5426   for(int i=0;i<nbOfCells;i++,ci++)
5427     {
5428       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5429         {
5430           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5431                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5432           pt=std::copy(tmp,tmp+8,pt);
5433           ptI[1]=ptI[0]+4;
5434           ptI[2]=ptI[0]+8;
5435           *retPt++=i;
5436           *retPt++=i;
5437           ptI+=2;
5438         }
5439       else
5440         {
5441           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5442           ptI[1]=ptI[0]+ci[1]-ci[0];
5443           ptI++;
5444           *retPt++=i;
5445         }
5446     }
5447   _nodal_connec->decrRef();
5448   _nodal_connec=newConn.retn();
5449   _nodal_connec_index->decrRef();
5450   _nodal_connec_index=newConnI.retn();
5451   computeTypes();
5452   updateTime();
5453   return ret.retn();
5454 }
5455
5456 /*!
5457  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5458  */
5459 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5460 {
5461   checkConnectivityFullyDefined();
5462   if(getMeshDimension()!=2)
5463     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5464   int nbOfCells=getNumberOfCells();
5465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5466   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5467   ret->alloc(nbOfCells+nbOfCutCells,1);
5468   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5469   int *retPt=ret->getPointer();
5470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5472   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5473   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5474   int *pt=newConn->getPointer();
5475   int *ptI=newConnI->getPointer();
5476   ptI[0]=0;
5477   const int *oldc=_nodal_connec->getConstPointer();
5478   const int *ci=_nodal_connec_index->getConstPointer();
5479   for(int i=0;i<nbOfCells;i++,ci++)
5480     {
5481       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5482         {
5483           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5484                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5485           pt=std::copy(tmp,tmp+8,pt);
5486           ptI[1]=ptI[0]+4;
5487           ptI[2]=ptI[0]+8;
5488           *retPt++=i;
5489           *retPt++=i;
5490           ptI+=2;
5491         }
5492       else
5493         {
5494           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5495           ptI[1]=ptI[0]+ci[1]-ci[0];
5496           ptI++;
5497           *retPt++=i;
5498         }
5499     }
5500   _nodal_connec->decrRef();
5501   _nodal_connec=newConn.retn();
5502   _nodal_connec_index->decrRef();
5503   _nodal_connec_index=newConnI.retn();
5504   computeTypes();
5505   updateTime();
5506   return ret.retn();
5507 }
5508
5509 /*!
5510  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5511  */
5512 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5513 {
5514   checkConnectivityFullyDefined();
5515   if(getMeshDimension()!=3)
5516     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5517   int nbOfCells=getNumberOfCells();
5518   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5519   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5520   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5521   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5522   int *retPt=ret->getPointer();
5523   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5524   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5525   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5526   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5527   int *pt=newConn->getPointer();
5528   int *ptI=newConnI->getPointer();
5529   ptI[0]=0;
5530   const int *oldc=_nodal_connec->getConstPointer();
5531   const int *ci=_nodal_connec_index->getConstPointer();
5532   for(int i=0;i<nbOfCells;i++,ci++)
5533     {
5534       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5535         {
5536           for(int j=0;j<5;j++,pt+=5,ptI++)
5537             {
5538               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5539               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];
5540               *retPt++=i;
5541               ptI[1]=ptI[0]+5;
5542             }
5543         }
5544       else
5545         {
5546           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5547           ptI[1]=ptI[0]+ci[1]-ci[0];
5548           ptI++;
5549           *retPt++=i;
5550         }
5551     }
5552   _nodal_connec->decrRef();
5553   _nodal_connec=newConn.retn();
5554   _nodal_connec_index->decrRef();
5555   _nodal_connec_index=newConnI.retn();
5556   computeTypes();
5557   updateTime();
5558   return ret.retn();
5559 }
5560
5561 /*!
5562  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5563  */
5564 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5565 {
5566   checkConnectivityFullyDefined();
5567   if(getMeshDimension()!=3)
5568     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5569   int nbOfCells=getNumberOfCells();
5570   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5571   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5572   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5573   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5574   int *retPt=ret->getPointer();
5575   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5577   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5578   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5579   int *pt=newConn->getPointer();
5580   int *ptI=newConnI->getPointer();
5581   ptI[0]=0;
5582   const int *oldc=_nodal_connec->getConstPointer();
5583   const int *ci=_nodal_connec_index->getConstPointer();
5584   for(int i=0;i<nbOfCells;i++,ci++)
5585     {
5586       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5587         {
5588           for(int j=0;j<6;j++,pt+=5,ptI++)
5589             {
5590               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5591               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];
5592               *retPt++=i;
5593               ptI[1]=ptI[0]+5;
5594             }
5595         }
5596       else
5597         {
5598           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5599           ptI[1]=ptI[0]+ci[1]-ci[0];
5600           ptI++;
5601           *retPt++=i;
5602         }
5603     }
5604   _nodal_connec->decrRef();
5605   _nodal_connec=newConn.retn();
5606   _nodal_connec_index->decrRef();
5607   _nodal_connec_index=newConnI.retn();
5608   computeTypes();
5609   updateTime();
5610   return ret.retn();
5611 }
5612
5613 /*!
5614  * 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.
5615  * This method completly ignore coordinates.
5616  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5617  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5618  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5619  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5620  */
5621 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5622 {
5623   checkFullyDefined();
5624   if(getMeshDimension()!=2)
5625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5626   int nbOfCells=getNumberOfCells();
5627   int *connI=_nodal_connec_index->getPointer();
5628   int newConnLgth=0;
5629   for(int i=0;i<nbOfCells;i++,connI++)
5630     {
5631       int offset=descIndex[i];
5632       int nbOfEdges=descIndex[i+1]-offset;
5633       //
5634       bool ddirect=desc[offset+nbOfEdges-1]>0;
5635       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5636       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5637       for(int j=0;j<nbOfEdges;j++)
5638         {
5639           bool direct=desc[offset+j]>0;
5640           int edgeId=std::abs(desc[offset+j])-1;
5641           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5642             {
5643               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5644               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5645               int ref2=direct?id1:id2;
5646               if(ref==ref2)
5647                 {
5648                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5649                   newConnLgth+=nbOfSubNodes-1;
5650                   ref=direct?id2:id1;
5651                 }
5652               else
5653                 {
5654                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5655                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5656                 }
5657             }
5658           else
5659             {
5660               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5661             }
5662         }
5663       newConnLgth++;//+1 is for cell type
5664       connI[1]=newConnLgth;
5665     }
5666   //
5667   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5668   newConn->alloc(newConnLgth,1);
5669   int *work=newConn->getPointer();
5670   for(int i=0;i<nbOfCells;i++)
5671     {
5672       *work++=INTERP_KERNEL::NORM_POLYGON;
5673       int offset=descIndex[i];
5674       int nbOfEdges=descIndex[i+1]-offset;
5675       for(int j=0;j<nbOfEdges;j++)
5676         {
5677           bool direct=desc[offset+j]>0;
5678           int edgeId=std::abs(desc[offset+j])-1;
5679           if(direct)
5680             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5681           else
5682             {
5683               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5684               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5685               work=std::copy(it,it+nbOfSubNodes-1,work);
5686             }
5687         }
5688     }
5689   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5690   _types.clear();
5691   if(nbOfCells>0)
5692     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5693 }
5694
5695 /*!
5696  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5697  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5698  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5699  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5700  * so it can be useful to call mergeNodes() before calling this method.
5701  *  \throw If \a this->getMeshDimension() <= 1.
5702  *  \throw If the coordinates array is not set.
5703  *  \throw If the nodal connectivity of cells is not defined.
5704  */
5705 void MEDCouplingUMesh::convertDegeneratedCells()
5706 {
5707   checkFullyDefined();
5708   if(getMeshDimension()<=1)
5709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5710   int nbOfCells=getNumberOfCells();
5711   if(nbOfCells<1)
5712     return ;
5713   int initMeshLgth=getMeshLength();
5714   int *conn=_nodal_connec->getPointer();
5715   int *index=_nodal_connec_index->getPointer();
5716   int posOfCurCell=0;
5717   int newPos=0;
5718   int lgthOfCurCell;
5719   for(int i=0;i<nbOfCells;i++)
5720     {
5721       lgthOfCurCell=index[i+1]-posOfCurCell;
5722       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5723       int newLgth;
5724       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5725                                                                                                      conn+newPos+1,newLgth);
5726       conn[newPos]=newType;
5727       newPos+=newLgth+1;
5728       posOfCurCell=index[i+1];
5729       index[i+1]=newPos;
5730     }
5731   if(newPos!=initMeshLgth)
5732     _nodal_connec->reAlloc(newPos);
5733   computeTypes();
5734 }
5735
5736 /*!
5737  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5738  * A cell is considered to be oriented correctly if an angle between its
5739  * normal vector and a given vector is less than \c PI / \c 2.
5740  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5741  *         cells. 
5742  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5743  *         checked.
5744  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5745  *         is not cleared before filling in.
5746  *  \throw If \a this->getMeshDimension() != 2.
5747  *  \throw If \a this->getSpaceDimension() != 3.
5748  *
5749  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5750  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5751  */
5752 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5753 {
5754   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5755     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5756   int nbOfCells=getNumberOfCells();
5757   const int *conn=_nodal_connec->getConstPointer();
5758   const int *connI=_nodal_connec_index->getConstPointer();
5759   const double *coordsPtr=_coords->getConstPointer();
5760   for(int i=0;i<nbOfCells;i++)
5761     {
5762       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5763       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5764         {
5765           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5766           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5767             cells.push_back(i);
5768         }
5769     }
5770 }
5771
5772 /*!
5773  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5774  * considered to be oriented correctly if an angle between its normal vector and a
5775  * given vector is less than \c PI / \c 2. 
5776  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5777  *         cells. 
5778  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5779  *         checked.
5780  *  \throw If \a this->getMeshDimension() != 2.
5781  *  \throw If \a this->getSpaceDimension() != 3.
5782  *
5783  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5784  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5785  */
5786 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5787 {
5788   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5789     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5790   int nbOfCells=getNumberOfCells();
5791   int *conn=_nodal_connec->getPointer();
5792   const int *connI=_nodal_connec_index->getConstPointer();
5793   const double *coordsPtr=_coords->getConstPointer();
5794   bool isModified=false;
5795   for(int i=0;i<nbOfCells;i++)
5796     {
5797       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5798       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5799         {
5800           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5801           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5802             {
5803               isModified=true;
5804               if(!isQuadratic)
5805                 {
5806                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5807                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5808                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5809                 }
5810               else
5811                 {
5812                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5813                   std::vector<int> tmp0(sz-1),tmp1(sz);
5814                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5815                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5816                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5817                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5818                 }
5819             }
5820         }
5821     }
5822   if(isModified)
5823     _nodal_connec->declareAsNew();
5824   updateTime();
5825 }
5826
5827 /*!
5828  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5829  * oriented facets. The normal vector of the facet should point out of the cell.
5830  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5831  *         is not cleared before filling in.
5832  *  \throw If \a this->getMeshDimension() != 3.
5833  *  \throw If \a this->getSpaceDimension() != 3.
5834  *  \throw If the coordinates array is not set.
5835  *  \throw If the nodal connectivity of cells is not defined.
5836  *
5837  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5838  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5839  */
5840 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5841 {
5842   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5843     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5844   int nbOfCells=getNumberOfCells();
5845   const int *conn=_nodal_connec->getConstPointer();
5846   const int *connI=_nodal_connec_index->getConstPointer();
5847   const double *coordsPtr=_coords->getConstPointer();
5848   for(int i=0;i<nbOfCells;i++)
5849     {
5850       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5851       if(type==INTERP_KERNEL::NORM_POLYHED)
5852         {
5853           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5854             cells.push_back(i);
5855         }
5856     }
5857 }
5858
5859 /*!
5860  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5861  * out of the cell. 
5862  *  \throw If \a this->getMeshDimension() != 3.
5863  *  \throw If \a this->getSpaceDimension() != 3.
5864  *  \throw If the coordinates array is not set.
5865  *  \throw If the nodal connectivity of cells is not defined.
5866  *  \throw If the reparation fails.
5867  *
5868  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5869  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5870  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5871  */
5872 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5873 {
5874   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5875     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5876   int nbOfCells=getNumberOfCells();
5877   int *conn=_nodal_connec->getPointer();
5878   const int *connI=_nodal_connec_index->getConstPointer();
5879   const double *coordsPtr=_coords->getConstPointer();
5880   for(int i=0;i<nbOfCells;i++)
5881     {
5882       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5883       if(type==INTERP_KERNEL::NORM_POLYHED)
5884         {
5885           try
5886             {
5887               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5888                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5889             }
5890           catch(INTERP_KERNEL::Exception& e)
5891             {
5892               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5893               throw INTERP_KERNEL::Exception(oss.str().c_str());
5894             }
5895         }
5896     }
5897   updateTime();
5898 }
5899
5900 /*!
5901  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5902  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5903  * according to which the first facet of the cell should be oriented to have the normal vector
5904  * pointing out of cell.
5905  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5906  *         cells. The caller is to delete this array using decrRef() as it is no more
5907  *         needed. 
5908  *  \throw If \a this->getMeshDimension() != 3.
5909  *  \throw If \a this->getSpaceDimension() != 3.
5910  *  \throw If the coordinates array is not set.
5911  *  \throw If the nodal connectivity of cells is not defined.
5912  *
5913  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5914  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5915  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5916  */
5917 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5918 {
5919   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5920   if(getMeshDimension()!=3)
5921     throw INTERP_KERNEL::Exception(msg);
5922   int spaceDim=getSpaceDimension();
5923   if(spaceDim!=3)
5924     throw INTERP_KERNEL::Exception(msg);
5925   //
5926   int nbOfCells=getNumberOfCells();
5927   int *conn=_nodal_connec->getPointer();
5928   const int *connI=_nodal_connec_index->getConstPointer();
5929   const double *coo=getCoords()->getConstPointer();
5930   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5931   for(int i=0;i<nbOfCells;i++)
5932     {
5933       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5934       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5935         {
5936           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5937             {
5938               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5939               cells->pushBackSilent(i);
5940             }
5941         }
5942     }
5943   return cells.retn();
5944 }
5945
5946 /*!
5947  * This method is a faster method to correct orientation of all 3D cells in \a this.
5948  * 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.
5949  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5950  * 
5951  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5952  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5953  */
5954 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5955 {
5956   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5957     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5958   int nbOfCells=getNumberOfCells();
5959   int *conn=_nodal_connec->getPointer();
5960   const int *connI=_nodal_connec_index->getConstPointer();
5961   const double *coordsPtr=_coords->getConstPointer();
5962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5963   for(int i=0;i<nbOfCells;i++)
5964     {
5965       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5966       switch(type)
5967         {
5968         case INTERP_KERNEL::NORM_TETRA4:
5969           {
5970             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5971               {
5972                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5973                 ret->pushBackSilent(i);
5974               }
5975             break;
5976           }
5977         case INTERP_KERNEL::NORM_PYRA5:
5978           {
5979             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5980               {
5981                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5982                 ret->pushBackSilent(i);
5983               }
5984             break;
5985           }
5986         case INTERP_KERNEL::NORM_PENTA6:
5987         case INTERP_KERNEL::NORM_HEXA8:
5988         case INTERP_KERNEL::NORM_HEXGP12:
5989           {
5990             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5991               {
5992                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5993                 ret->pushBackSilent(i);
5994               }
5995             break;
5996           }
5997         case INTERP_KERNEL::NORM_POLYHED:
5998           {
5999             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6000               {
6001                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6002                 ret->pushBackSilent(i);
6003               }
6004             break;
6005           }
6006         default:
6007           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 !");
6008         }
6009     }
6010   updateTime();
6011   return ret.retn();
6012 }
6013
6014 /*!
6015  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6016  * If it is not the case an exception will be thrown.
6017  * This method is fast because the first cell of \a this is used to compute the plane.
6018  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6019  * \param pos output of size at least 3 used to store a point owned of searched plane.
6020  */
6021 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6022 {
6023   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6024     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6025   const int *conn=_nodal_connec->getConstPointer();
6026   const int *connI=_nodal_connec_index->getConstPointer();
6027   const double *coordsPtr=_coords->getConstPointer();
6028   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6029   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6030 }
6031
6032 /*!
6033  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6034  * cells. Currently cells of the following types are treated:
6035  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6036  * For a cell of other type an exception is thrown.
6037  * Space dimension of a 2D mesh can be either 2 or 3.
6038  * The Edge Ratio of a cell \f$t\f$ is: 
6039  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6040  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6041  *  the smallest edge lengths of \f$t\f$.
6042  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6043  *          cells and one time, lying on \a this mesh. The caller is to delete this
6044  *          field using decrRef() as it is no more needed. 
6045  *  \throw If the coordinates array is not set.
6046  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6047  *  \throw If the connectivity data array has more than one component.
6048  *  \throw If the connectivity data array has a named component.
6049  *  \throw If the connectivity index data array has more than one component.
6050  *  \throw If the connectivity index data array has a named component.
6051  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6052  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6053  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6054  */
6055 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6056 {
6057   checkCoherency();
6058   int spaceDim=getSpaceDimension();
6059   int meshDim=getMeshDimension();
6060   if(spaceDim!=2 && spaceDim!=3)
6061     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6062   if(meshDim!=2 && meshDim!=3)
6063     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6064   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6065   ret->setMesh(this);
6066   int nbOfCells=getNumberOfCells();
6067   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6068   arr->alloc(nbOfCells,1);
6069   double *pt=arr->getPointer();
6070   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6071   const int *conn=_nodal_connec->getConstPointer();
6072   const int *connI=_nodal_connec_index->getConstPointer();
6073   const double *coo=_coords->getConstPointer();
6074   double tmp[12];
6075   for(int i=0;i<nbOfCells;i++,pt++)
6076     {
6077       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6078       switch(t)
6079         {
6080           case INTERP_KERNEL::NORM_TRI3:
6081             {
6082               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6083               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6084               break;
6085             }
6086           case INTERP_KERNEL::NORM_QUAD4:
6087             {
6088               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6089               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6090               break;
6091             }
6092           case INTERP_KERNEL::NORM_TETRA4:
6093             {
6094               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6095               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6096               break;
6097             }
6098         default:
6099           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6100         }
6101       conn+=connI[i+1]-connI[i];
6102     }
6103   ret->setName("EdgeRatio");
6104   ret->synchronizeTimeWithSupport();
6105   return ret.retn();
6106 }
6107
6108 /*!
6109  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6110  * cells. Currently cells of the following types are treated:
6111  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6112  * For a cell of other type an exception is thrown.
6113  * Space dimension of a 2D mesh can be either 2 or 3.
6114  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6115  *          cells and one time, lying on \a this mesh. The caller is to delete this
6116  *          field using decrRef() as it is no more needed. 
6117  *  \throw If the coordinates array is not set.
6118  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6119  *  \throw If the connectivity data array has more than one component.
6120  *  \throw If the connectivity data array has a named component.
6121  *  \throw If the connectivity index data array has more than one component.
6122  *  \throw If the connectivity index data array has a named component.
6123  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6124  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6125  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6126  */
6127 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6128 {
6129   checkCoherency();
6130   int spaceDim=getSpaceDimension();
6131   int meshDim=getMeshDimension();
6132   if(spaceDim!=2 && spaceDim!=3)
6133     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6134   if(meshDim!=2 && meshDim!=3)
6135     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6136   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6137   ret->setMesh(this);
6138   int nbOfCells=getNumberOfCells();
6139   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6140   arr->alloc(nbOfCells,1);
6141   double *pt=arr->getPointer();
6142   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6143   const int *conn=_nodal_connec->getConstPointer();
6144   const int *connI=_nodal_connec_index->getConstPointer();
6145   const double *coo=_coords->getConstPointer();
6146   double tmp[12];
6147   for(int i=0;i<nbOfCells;i++,pt++)
6148     {
6149       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6150       switch(t)
6151         {
6152           case INTERP_KERNEL::NORM_TRI3:
6153             {
6154               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6155               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6156               break;
6157             }
6158           case INTERP_KERNEL::NORM_QUAD4:
6159             {
6160               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6161               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6162               break;
6163             }
6164           case INTERP_KERNEL::NORM_TETRA4:
6165             {
6166               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6167               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6168               break;
6169             }
6170         default:
6171           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6172         }
6173       conn+=connI[i+1]-connI[i];
6174     }
6175   ret->setName("AspectRatio");
6176   ret->synchronizeTimeWithSupport();
6177   return ret.retn();
6178 }
6179
6180 /*!
6181  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6182  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6183  * treated: INTERP_KERNEL::NORM_QUAD4.
6184  * For a cell of other type an exception is thrown.
6185  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6186  *          cells and one time, lying on \a this mesh. The caller is to delete this
6187  *          field using decrRef() as it is no more needed. 
6188  *  \throw If the coordinates array is not set.
6189  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6190  *  \throw If the connectivity data array has more than one component.
6191  *  \throw If the connectivity data array has a named component.
6192  *  \throw If the connectivity index data array has more than one component.
6193  *  \throw If the connectivity index data array has a named component.
6194  *  \throw If \a this->getMeshDimension() != 2.
6195  *  \throw If \a this->getSpaceDimension() != 3.
6196  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6197  */
6198 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6199 {
6200   checkCoherency();
6201   int spaceDim=getSpaceDimension();
6202   int meshDim=getMeshDimension();
6203   if(spaceDim!=3)
6204     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6205   if(meshDim!=2)
6206     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6207   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6208   ret->setMesh(this);
6209   int nbOfCells=getNumberOfCells();
6210   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6211   arr->alloc(nbOfCells,1);
6212   double *pt=arr->getPointer();
6213   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6214   const int *conn=_nodal_connec->getConstPointer();
6215   const int *connI=_nodal_connec_index->getConstPointer();
6216   const double *coo=_coords->getConstPointer();
6217   double tmp[12];
6218   for(int i=0;i<nbOfCells;i++,pt++)
6219     {
6220       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6221       switch(t)
6222         {
6223           case INTERP_KERNEL::NORM_QUAD4:
6224             {
6225               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6226               *pt=INTERP_KERNEL::quadWarp(tmp);
6227               break;
6228             }
6229         default:
6230           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6231         }
6232       conn+=connI[i+1]-connI[i];
6233     }
6234   ret->setName("Warp");
6235   ret->synchronizeTimeWithSupport();
6236   return ret.retn();
6237 }
6238
6239
6240 /*!
6241  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6242  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6243  * treated: INTERP_KERNEL::NORM_QUAD4.
6244  * For a cell of other type an exception is thrown.
6245  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6246  *          cells and one time, lying on \a this mesh. The caller is to delete this
6247  *          field using decrRef() as it is no more needed. 
6248  *  \throw If the coordinates array is not set.
6249  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6250  *  \throw If the connectivity data array has more than one component.
6251  *  \throw If the connectivity data array has a named component.
6252  *  \throw If the connectivity index data array has more than one component.
6253  *  \throw If the connectivity index data array has a named component.
6254  *  \throw If \a this->getMeshDimension() != 2.
6255  *  \throw If \a this->getSpaceDimension() != 3.
6256  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6257  */
6258 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6259 {
6260   checkCoherency();
6261   int spaceDim=getSpaceDimension();
6262   int meshDim=getMeshDimension();
6263   if(spaceDim!=3)
6264     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6265   if(meshDim!=2)
6266     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6267   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6268   ret->setMesh(this);
6269   int nbOfCells=getNumberOfCells();
6270   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6271   arr->alloc(nbOfCells,1);
6272   double *pt=arr->getPointer();
6273   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6274   const int *conn=_nodal_connec->getConstPointer();
6275   const int *connI=_nodal_connec_index->getConstPointer();
6276   const double *coo=_coords->getConstPointer();
6277   double tmp[12];
6278   for(int i=0;i<nbOfCells;i++,pt++)
6279     {
6280       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6281       switch(t)
6282         {
6283           case INTERP_KERNEL::NORM_QUAD4:
6284             {
6285               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6286               *pt=INTERP_KERNEL::quadSkew(tmp);
6287               break;
6288             }
6289         default:
6290           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6291         }
6292       conn+=connI[i+1]-connI[i];
6293     }
6294   ret->setName("Skew");
6295   ret->synchronizeTimeWithSupport();
6296   return ret.retn();
6297 }
6298
6299 /*!
6300  * This method aggregate the bbox of each cell and put it into bbox parameter.
6301  * 
6302  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6303  *                         For all other cases this input parameter is ignored.
6304  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6305  * 
6306  * \throw If \a this is not fully set (coordinates and connectivity).
6307  * \throw If a cell in \a this has no valid nodeId.
6308  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6309  */
6310 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6311 {
6312   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6313   if((mDim==3 && sDim==3) || (mDim==2 && sDim==3) || (mDim==1 && sDim==1) || ( mDim==1 && sDim==3))  // Compute refined boundary box for quadratic elements only in 2D.
6314     return getBoundingBoxForBBTreeFast();
6315   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6316     {
6317       bool presenceOfQuadratic(false);
6318       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6319         {
6320           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6321           if(cm.isQuadratic())
6322             presenceOfQuadratic=true;
6323         }
6324       if(!presenceOfQuadratic)
6325         return getBoundingBoxForBBTreeFast();
6326       if(mDim==2 && sDim==2)
6327         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6328       else
6329         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6330     }
6331   throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree : Managed dimensions are (mDim=1,sDim=1), (mDim=1,sDim=2), (mDim=1,sDim=3), (mDim=2,sDim=2), (mDim=2,sDim=3) and (mDim=3,sDim=3) !");
6332 }
6333
6334 /*!
6335  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6336  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6337  * 
6338  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6339  * 
6340  * \throw If \a this is not fully set (coordinates and connectivity).
6341  * \throw If a cell in \a this has no valid nodeId.
6342  */
6343 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6344 {
6345   checkFullyDefined();
6346   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6347   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6348   double *bbox(ret->getPointer());
6349   for(int i=0;i<nbOfCells*spaceDim;i++)
6350     {
6351       bbox[2*i]=std::numeric_limits<double>::max();
6352       bbox[2*i+1]=-std::numeric_limits<double>::max();
6353     }
6354   const double *coordsPtr(_coords->getConstPointer());
6355   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6356   for(int i=0;i<nbOfCells;i++)
6357     {
6358       int offset=connI[i]+1;
6359       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6360       for(int j=0;j<nbOfNodesForCell;j++)
6361         {
6362           int nodeId=conn[offset+j];
6363           if(nodeId>=0 && nodeId<nbOfNodes)
6364             {
6365               for(int k=0;k<spaceDim;k++)
6366                 {
6367                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6368                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6369                 }
6370               kk++;
6371             }
6372         }
6373       if(kk==0)
6374         {
6375           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6376           throw INTERP_KERNEL::Exception(oss.str().c_str());
6377         }
6378     }
6379   return ret.retn();
6380 }
6381
6382 /*!
6383  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6384  * useful for 2D meshes having quadratic cells
6385  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6386  * the two extremities of the arc of circle).
6387  * 
6388  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6389  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6390  * \throw If \a this is not fully defined.
6391  * \throw If \a this is not a mesh with meshDimension equal to 2.
6392  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6393  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6394  */
6395 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6396 {
6397   checkFullyDefined();
6398   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6399   if(spaceDim!=2 || mDim!=2)
6400     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic : This method should be applied on mesh with mesh dimension equal to 2 and space dimension also equal to 2!");
6401   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6402   double *bbox(ret->getPointer());
6403   const double *coords(_coords->getConstPointer());
6404   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6405   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6406     {
6407       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6408       int sz(connI[1]-connI[0]-1);
6409       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6410       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6411       INTERP_KERNEL::QuadraticPolygon *pol(0);
6412       for(int j=0;j<sz;j++)
6413         {
6414           int nodeId(conn[*connI+1+j]);
6415           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6416         }
6417       if(!cm.isQuadratic())
6418         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6419       else
6420         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6421       INTERP_KERNEL::Bounds b; pol->fillBounds(b); delete pol;
6422       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6423     }
6424   return ret.retn();
6425 }
6426
6427 /*!
6428  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6429  * useful for 2D meshes having quadratic cells
6430  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6431  * the two extremities of the arc of circle).
6432  * 
6433  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6434  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6435  * \throw If \a this is not fully defined.
6436  * \throw If \a this is not a mesh with meshDimension equal to 1.
6437  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6438  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6439  */
6440 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6441 {
6442   checkFullyDefined();
6443   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6444   if(spaceDim!=2 || mDim!=1)
6445     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic : This method should be applied on mesh with mesh dimension equal to 1 and space dimension also equal to 2!");
6446   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6447   double *bbox(ret->getPointer());
6448   const double *coords(_coords->getConstPointer());
6449   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6450   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6451     {
6452       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6453       int sz(connI[1]-connI[0]-1);
6454       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6455       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6456       INTERP_KERNEL::Edge *edge(0);
6457       for(int j=0;j<sz;j++)
6458         {
6459           int nodeId(conn[*connI+1+j]);
6460           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6461         }
6462       if(!cm.isQuadratic())
6463         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6464       else
6465         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6466       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6467       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6468     }
6469   return ret.retn();
6470 }
6471
6472 /// @cond INTERNAL
6473
6474 namespace ParaMEDMEMImpl
6475 {
6476   class ConnReader
6477   {
6478   public:
6479     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6480     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6481   private:
6482     const int *_conn;
6483     int _val;
6484   };
6485
6486   class ConnReader2
6487   {
6488   public:
6489     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6490     bool operator() (const int& pos) { return _conn[pos]==_val; }
6491   private:
6492     const int *_conn;
6493     int _val;
6494   };
6495 }
6496
6497 /// @endcond
6498
6499 /*!
6500  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6501  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6502  * \a this is composed in cell types.
6503  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6504  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6505  * This parameter is kept only for compatibility with other methode listed above.
6506  */
6507 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6508 {
6509   checkConnectivityFullyDefined();
6510   const int *conn=_nodal_connec->getConstPointer();
6511   const int *connI=_nodal_connec_index->getConstPointer();
6512   const int *work=connI;
6513   int nbOfCells=getNumberOfCells();
6514   std::size_t n=getAllGeoTypes().size();
6515   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6516   std::set<INTERP_KERNEL::NormalizedCellType> types;
6517   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6518     {
6519       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6520       if(types.find(typ)!=types.end())
6521         {
6522           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6523           oss << " is not contiguous !";
6524           throw INTERP_KERNEL::Exception(oss.str().c_str());
6525         }
6526       types.insert(typ);
6527       ret[3*i]=typ;
6528       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6529       ret[3*i+1]=(int)std::distance(work,work2);
6530       work=work2;
6531     }
6532   return ret;
6533 }
6534
6535 /*!
6536  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6537  * only for types cell, type node is not managed.
6538  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6539  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6540  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6541  * If 2 or more same geometric type is in \a code and exception is thrown too.
6542  *
6543  * This method firstly checks
6544  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6545  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6546  * an exception is thrown too.
6547  * 
6548  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6549  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6550  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6551  */
6552 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6553 {
6554   if(code.empty())
6555     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6556   std::size_t sz=code.size();
6557   std::size_t n=sz/3;
6558   if(sz%3!=0)
6559     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6560   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6561   int nb=0;
6562   bool isNoPflUsed=true;
6563   for(std::size_t i=0;i<n;i++)
6564     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6565       {
6566         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6567         nb+=code[3*i+1];
6568         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6569           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6570         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6571       }
6572   if(types.size()!=n)
6573     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6574   if(isNoPflUsed)
6575     {
6576       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6577         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6578       if(types.size()==_types.size())
6579         return 0;
6580     }
6581   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6582   ret->alloc(nb,1);
6583   int *retPtr=ret->getPointer();
6584   const int *connI=_nodal_connec_index->getConstPointer();
6585   const int *conn=_nodal_connec->getConstPointer();
6586   int nbOfCells=getNumberOfCells();
6587   const int *i=connI;
6588   int kk=0;
6589   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6590     {
6591       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6592       int offset=(int)std::distance(connI,i);
6593       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6594       int nbOfCellsOfCurType=(int)std::distance(i,j);
6595       if(code[3*kk+2]==-1)
6596         for(int k=0;k<nbOfCellsOfCurType;k++)
6597           *retPtr++=k+offset;
6598       else
6599         {
6600           int idInIdsPerType=code[3*kk+2];
6601           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6602             {
6603               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6604               if(zePfl)
6605                 {
6606                   zePfl->checkAllocated();
6607                   if(zePfl->getNumberOfComponents()==1)
6608                     {
6609                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6610                         {
6611                           if(*k>=0 && *k<nbOfCellsOfCurType)
6612                             *retPtr=(*k)+offset;
6613                           else
6614                             {
6615                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6616                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6617                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6618                             }
6619                         }
6620                     }
6621                   else
6622                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6623                 }
6624               else
6625                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6626             }
6627           else
6628             {
6629               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6630               oss << " should be in [0," << idsPerType.size() << ") !";
6631               throw INTERP_KERNEL::Exception(oss.str().c_str());
6632             }
6633         }
6634       i=j;
6635     }
6636   return ret.retn();
6637 }
6638
6639 /*!
6640  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6641  * 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.
6642  * 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.
6643  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6644  * 
6645  * \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.
6646  * \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,
6647  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6648  * \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.
6649  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6650  * \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
6651  */
6652 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6653 {
6654   if(!profile)
6655     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6656   if(profile->getNumberOfComponents()!=1)
6657     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6658   checkConnectivityFullyDefined();
6659   const int *conn=_nodal_connec->getConstPointer();
6660   const int *connI=_nodal_connec_index->getConstPointer();
6661   int nbOfCells=getNumberOfCells();
6662   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6663   std::vector<int> typeRangeVals(1);
6664   for(const int *i=connI;i!=connI+nbOfCells;)
6665     {
6666       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6667       if(std::find(types.begin(),types.end(),curType)!=types.end())
6668         {
6669           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6670         }
6671       types.push_back(curType);
6672       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6673       typeRangeVals.push_back((int)std::distance(connI,i));
6674     }
6675   //
6676   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6677   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6678   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6679   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6680   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6681   //
6682   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6683   code.resize(3*nbOfCastsFinal);
6684   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6685   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6686   for(int i=0;i<nbOfCastsFinal;i++)
6687     {
6688       int castId=castsPresent->getIJ(i,0);
6689       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6690       idsInPflPerType2.push_back(tmp3);
6691       code[3*i]=(int)types[castId];
6692       code[3*i+1]=tmp3->getNumberOfTuples();
6693       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6694       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6695         {
6696           tmp4->copyStringInfoFrom(*profile);
6697           idsPerType2.push_back(tmp4);
6698           code[3*i+2]=(int)idsPerType2.size()-1;
6699         }
6700       else
6701         {
6702           code[3*i+2]=-1;
6703         }
6704     }
6705   std::size_t sz2=idsInPflPerType2.size();
6706   idsInPflPerType.resize(sz2);
6707   for(std::size_t i=0;i<sz2;i++)
6708     {
6709       DataArrayInt *locDa=idsInPflPerType2[i];
6710       locDa->incrRef();
6711       idsInPflPerType[i]=locDa;
6712     }
6713   std::size_t sz=idsPerType2.size();
6714   idsPerType.resize(sz);
6715   for(std::size_t i=0;i<sz;i++)
6716     {
6717       DataArrayInt *locDa=idsPerType2[i];
6718       locDa->incrRef();
6719       idsPerType[i]=locDa;
6720     }
6721 }
6722
6723 /*!
6724  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6725  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6726  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6727  * 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.
6728  */
6729 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6730 {
6731   checkFullyDefined();
6732   nM1LevMesh->checkFullyDefined();
6733   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6734     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6735   if(_coords!=nM1LevMesh->getCoords())
6736     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6737   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6738   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6739   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6740   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6741   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6742   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6743   tmp->setConnectivity(tmp0,tmp1);
6744   tmp->renumberCells(ret0->getConstPointer(),false);
6745   revDesc=tmp->getNodalConnectivity();
6746   revDescIndx=tmp->getNodalConnectivityIndex();
6747   DataArrayInt *ret=0;
6748   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6749     {
6750       int tmp2;
6751       ret->getMaxValue(tmp2);
6752       ret->decrRef();
6753       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6754       throw INTERP_KERNEL::Exception(oss.str().c_str());
6755     }
6756   nM1LevMeshIds=ret;
6757   //
6758   revDesc->incrRef();
6759   revDescIndx->incrRef();
6760   ret1->incrRef();
6761   ret0->incrRef();
6762   meshnM1Old2New=ret0;
6763   return ret1;
6764 }
6765
6766 /*!
6767  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6768  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6769  * in "Old to New" mode.
6770  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6771  *          this array using decrRef() as it is no more needed.
6772  *  \throw If the nodal connectivity of cells is not defined.
6773  */
6774 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6775 {
6776   checkConnectivityFullyDefined();
6777   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6778   renumberCells(ret->getConstPointer(),false);
6779   return ret.retn();
6780 }
6781
6782 /*!
6783  * This methods checks that cells are sorted by their types.
6784  * This method makes asumption (no check) that connectivity is correctly set before calling.
6785  */
6786 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6787 {
6788   checkFullyDefined();
6789   const int *conn=_nodal_connec->getConstPointer();
6790   const int *connI=_nodal_connec_index->getConstPointer();
6791   int nbOfCells=getNumberOfCells();
6792   std::set<INTERP_KERNEL::NormalizedCellType> types;
6793   for(const int *i=connI;i!=connI+nbOfCells;)
6794     {
6795       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6796       if(types.find(curType)!=types.end())
6797         return false;
6798       types.insert(curType);
6799       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6800     }
6801   return true;
6802 }
6803
6804 /*!
6805  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6806  * The geometric type order is specified by MED file.
6807  * 
6808  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6809  */
6810 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6811 {
6812   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6813 }
6814
6815 /*!
6816  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6817  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6818  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6819  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6820  */
6821 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6822 {
6823   checkFullyDefined();
6824   const int *conn=_nodal_connec->getConstPointer();
6825   const int *connI=_nodal_connec_index->getConstPointer();
6826   int nbOfCells=getNumberOfCells();
6827   if(nbOfCells==0)
6828     return true;
6829   int lastPos=-1;
6830   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6831   for(const int *i=connI;i!=connI+nbOfCells;)
6832     {
6833       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6834       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6835       if(isTypeExists!=orderEnd)
6836         {
6837           int pos=(int)std::distance(orderBg,isTypeExists);
6838           if(pos<=lastPos)
6839             return false;
6840           lastPos=pos;
6841           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6842         }
6843       else
6844         {
6845           if(sg.find(curType)==sg.end())
6846             {
6847               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6848               sg.insert(curType);
6849             }
6850           else
6851             return false;
6852         }
6853     }
6854   return true;
6855 }
6856
6857 /*!
6858  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6859  * 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
6860  * 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'.
6861  */
6862 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6863 {
6864   checkConnectivityFullyDefined();
6865   int nbOfCells=getNumberOfCells();
6866   const int *conn=_nodal_connec->getConstPointer();
6867   const int *connI=_nodal_connec_index->getConstPointer();
6868   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6869   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6870   tmpa->alloc(nbOfCells,1);
6871   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6872   tmpb->fillWithZero();
6873   int *tmp=tmpa->getPointer();
6874   int *tmp2=tmpb->getPointer();
6875   for(const int *i=connI;i!=connI+nbOfCells;i++)
6876     {
6877       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6878       if(where!=orderEnd)
6879         {
6880           int pos=(int)std::distance(orderBg,where);
6881           tmp2[pos]++;
6882           tmp[std::distance(connI,i)]=pos;
6883         }
6884       else
6885         {
6886           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6887           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6888           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6889           throw INTERP_KERNEL::Exception(oss.str().c_str());
6890         }
6891     }
6892   nbPerType=tmpb.retn();
6893   return tmpa.retn();
6894 }
6895
6896 /*!
6897  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6898  *
6899  * \return a new object containing the old to new correspondance.
6900  *
6901  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6902  */
6903 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6904 {
6905   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6906 }
6907
6908 /*!
6909  * 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.
6910  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6911  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6912  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6913  */
6914 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6915 {
6916   DataArrayInt *nbPerType=0;
6917   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6918   nbPerType->decrRef();
6919   return tmpa->buildPermArrPerLevel();
6920 }
6921
6922 /*!
6923  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6924  * The number of cells remains unchanged after the call of this method.
6925  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6926  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6927  *
6928  * \return the array giving the correspondance old to new.
6929  */
6930 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6931 {
6932   checkFullyDefined();
6933   computeTypes();
6934   const int *conn=_nodal_connec->getConstPointer();
6935   const int *connI=_nodal_connec_index->getConstPointer();
6936   int nbOfCells=getNumberOfCells();
6937   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6938   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6939     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6940       {
6941         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6942         types.push_back(curType);
6943         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6944       }
6945   DataArrayInt *ret=DataArrayInt::New();
6946   ret->alloc(nbOfCells,1);
6947   int *retPtr=ret->getPointer();
6948   std::fill(retPtr,retPtr+nbOfCells,-1);
6949   int newCellId=0;
6950   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6951     {
6952       for(const int *i=connI;i!=connI+nbOfCells;i++)
6953         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6954           retPtr[std::distance(connI,i)]=newCellId++;
6955     }
6956   renumberCells(retPtr,false);
6957   return ret;
6958 }
6959
6960 /*!
6961  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6962  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6963  * This method makes asumption that connectivity is correctly set before calling.
6964  */
6965 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6966 {
6967   checkConnectivityFullyDefined();
6968   const int *conn=_nodal_connec->getConstPointer();
6969   const int *connI=_nodal_connec_index->getConstPointer();
6970   int nbOfCells=getNumberOfCells();
6971   std::vector<MEDCouplingUMesh *> ret;
6972   for(const int *i=connI;i!=connI+nbOfCells;)
6973     {
6974       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6975       int beginCellId=(int)std::distance(connI,i);
6976       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6977       int endCellId=(int)std::distance(connI,i);
6978       int sz=endCellId-beginCellId;
6979       int *cells=new int[sz];
6980       for(int j=0;j<sz;j++)
6981         cells[j]=beginCellId+j;
6982       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6983       delete [] cells;
6984       ret.push_back(m);
6985     }
6986   return ret;
6987 }
6988
6989 /*!
6990  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6991  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6992  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6993  *
6994  * \return a newly allocated instance, that the caller must manage.
6995  * \throw If \a this contains more than one geometric type.
6996  * \throw If the nodal connectivity of \a this is not fully defined.
6997  * \throw If the internal data is not coherent.
6998  */
6999 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7000 {
7001   checkConnectivityFullyDefined();
7002     if(_types.size()!=1)
7003     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7004   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7005   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7006   ret->setCoords(getCoords());
7007   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7008   if(retC)
7009     {
7010       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7011       retC->setNodalConnectivity(c);
7012     }
7013   else
7014     {
7015       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7016       if(!retD)
7017         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7018       DataArrayInt *c=0,*ci=0;
7019       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7020       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7021       retD->setNodalConnectivity(cs,cis);
7022     }
7023   return ret.retn();
7024 }
7025
7026 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7027 {
7028   checkConnectivityFullyDefined();
7029     if(_types.size()!=1)
7030     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7031   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7032   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7033   if(cm.isDynamic())
7034     {
7035       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7036       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7037       throw INTERP_KERNEL::Exception(oss.str().c_str());
7038     }
7039   int nbCells=getNumberOfCells();
7040   int typi=(int)typ;
7041   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7042   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7043   int *outPtr=connOut->getPointer();
7044   const int *conn=_nodal_connec->begin();
7045   const int *connI=_nodal_connec_index->begin();
7046   nbNodesPerCell++;
7047   for(int i=0;i<nbCells;i++,connI++)
7048     {
7049       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7050         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7051       else
7052         {
7053           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 << ") !";
7054           throw INTERP_KERNEL::Exception(oss.str().c_str());
7055         }
7056     }
7057   return connOut.retn();
7058 }
7059
7060 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7061 {
7062   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7063   checkConnectivityFullyDefined();
7064   if(_types.size()!=1)
7065     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7066   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7067   if(lgth<nbCells)
7068     throw INTERP_KERNEL::Exception(msg0);
7069   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7070   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7071   int *cp(c->getPointer()),*cip(ci->getPointer());
7072   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7073   cip[0]=0;
7074   for(int i=0;i<nbCells;i++,cip++,incip++)
7075     {
7076       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7077       int delta(stop-strt);
7078       if(delta>=1)
7079         {
7080           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7081             cp=std::copy(incp+strt,incp+stop,cp);
7082           else
7083             throw INTERP_KERNEL::Exception(msg0);
7084         }
7085       else
7086         throw INTERP_KERNEL::Exception(msg0);
7087       cip[1]=cip[0]+delta;
7088     }
7089   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7090 }
7091
7092 /*!
7093  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7094  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7095  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7096  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7097  * are not used here to avoid the build of big permutation array.
7098  *
7099  * \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
7100  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7101  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7102  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7103  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7104  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7105  * \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
7106  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7107  */
7108 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7109                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7110                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7111 {
7112   std::vector<const MEDCouplingUMesh *> ms2;
7113   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7114     if(*it)
7115       {
7116         (*it)->checkConnectivityFullyDefined();
7117         ms2.push_back(*it);
7118       }
7119   if(ms2.empty())
7120     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7121   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7122   int meshDim=ms2[0]->getMeshDimension();
7123   std::vector<const MEDCouplingUMesh *> m1ssm;
7124   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7125   //
7126   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7127   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7128   int fake=0,rk=0;
7129   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7130   ret1->alloc(0,1); ret2->alloc(0,1);
7131   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7132     {
7133       if(meshDim!=(*it)->getMeshDimension())
7134         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7135       if(refCoo!=(*it)->getCoords())
7136         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7137       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7138       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7139       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7140       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7141         {
7142           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7143           m1ssmSingleAuto.push_back(singleCell);
7144           m1ssmSingle.push_back(singleCell);
7145           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7146         }
7147     }
7148   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7149   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7150   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7151   for(std::size_t i=0;i<m1ssm.size();i++)
7152     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7153   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7154   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7155   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7156   return ret0.retn();
7157 }
7158
7159 /*!
7160  * This method returns a newly created DataArrayInt instance.
7161  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7162  */
7163 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7164 {
7165   checkFullyDefined();
7166   const int *conn=_nodal_connec->getConstPointer();
7167   const int *connIndex=_nodal_connec_index->getConstPointer();
7168   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7169   for(const int *w=begin;w!=end;w++)
7170     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7171       ret->pushBackSilent(*w);
7172   return ret.retn();
7173 }
7174
7175 /*!
7176  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7177  * are in [0:getNumberOfCells())
7178  */
7179 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7180 {
7181   checkFullyDefined();
7182   const int *conn=_nodal_connec->getConstPointer();
7183   const int *connI=_nodal_connec_index->getConstPointer();
7184   int nbOfCells=getNumberOfCells();
7185   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7186   int *tmp=new int[nbOfCells];
7187   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7188     {
7189       int j=0;
7190       for(const int *i=connI;i!=connI+nbOfCells;i++)
7191         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7192           tmp[std::distance(connI,i)]=j++;
7193     }
7194   DataArrayInt *ret=DataArrayInt::New();
7195   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7196   ret->copyStringInfoFrom(*da);
7197   int *retPtr=ret->getPointer();
7198   const int *daPtr=da->getConstPointer();
7199   int nbOfElems=da->getNbOfElems();
7200   for(int k=0;k<nbOfElems;k++)
7201     retPtr[k]=tmp[daPtr[k]];
7202   delete [] tmp;
7203   return ret;
7204 }
7205
7206 /*!
7207  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7208  * This method \b works \b for mesh sorted by type.
7209  * cells whose ids is in 'idsPerGeoType' array.
7210  * This method conserves coords and name of mesh.
7211  */
7212 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7213 {
7214   std::vector<int> code=getDistributionOfTypes();
7215   std::size_t nOfTypesInThis=code.size()/3;
7216   int sz=0,szOfType=0;
7217   for(std::size_t i=0;i<nOfTypesInThis;i++)
7218     {
7219       if(code[3*i]!=type)
7220         sz+=code[3*i+1];
7221       else
7222         szOfType=code[3*i+1];
7223     }
7224   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7225     if(*work<0 || *work>=szOfType)
7226       {
7227         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7228         oss << ". It should be in [0," << szOfType << ") !";
7229         throw INTERP_KERNEL::Exception(oss.str().c_str());
7230       }
7231   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7232   int *idsPtr=idsTokeep->getPointer();
7233   int offset=0;
7234   for(std::size_t i=0;i<nOfTypesInThis;i++)
7235     {
7236       if(code[3*i]!=type)
7237         for(int j=0;j<code[3*i+1];j++)
7238           *idsPtr++=offset+j;
7239       else
7240         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7241       offset+=code[3*i+1];
7242     }
7243   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7244   ret->copyTinyInfoFrom(this);
7245   return ret.retn();
7246 }
7247
7248 /*!
7249  * This method returns a vector of size 'this->getNumberOfCells()'.
7250  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7251  */
7252 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7253 {
7254   int ncell=getNumberOfCells();
7255   std::vector<bool> ret(ncell);
7256   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7257   const int *c=getNodalConnectivity()->getConstPointer();
7258   for(int i=0;i<ncell;i++)
7259     {
7260       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7261       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7262       ret[i]=cm.isQuadratic();
7263     }
7264   return ret;
7265 }
7266
7267 /*!
7268  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7269  */
7270 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7271 {
7272   if(other->getType()!=UNSTRUCTURED)
7273     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7274   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7275   return MergeUMeshes(this,otherC);
7276 }
7277
7278 /*!
7279  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7280  * computed by averaging coordinates of cell nodes, so this method is not a right
7281  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7282  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7283  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7284  *          components. The caller is to delete this array using decrRef() as it is
7285  *          no more needed.
7286  *  \throw If the coordinates array is not set.
7287  *  \throw If the nodal connectivity of cells is not defined.
7288  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7289  */
7290 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7291 {
7292   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7293   int spaceDim=getSpaceDimension();
7294   int nbOfCells=getNumberOfCells();
7295   ret->alloc(nbOfCells,spaceDim);
7296   ret->copyStringInfoFrom(*getCoords());
7297   double *ptToFill=ret->getPointer();
7298   const int *nodal=_nodal_connec->getConstPointer();
7299   const int *nodalI=_nodal_connec_index->getConstPointer();
7300   const double *coor=_coords->getConstPointer();
7301   for(int i=0;i<nbOfCells;i++)
7302     {
7303       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7304       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7305       ptToFill+=spaceDim;
7306     }
7307   return ret.retn();
7308 }
7309
7310 /*!
7311  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7312  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7313  * 
7314  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7315  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7316  * 
7317  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7318  * \throw If \a this is not fully defined (coordinates and connectivity)
7319  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7320  */
7321 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7322 {
7323   checkFullyDefined();
7324   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7325   int spaceDim=getSpaceDimension();
7326   int nbOfCells=getNumberOfCells();
7327   int nbOfNodes=getNumberOfNodes();
7328   ret->alloc(nbOfCells,spaceDim);
7329   double *ptToFill=ret->getPointer();
7330   const int *nodal=_nodal_connec->getConstPointer();
7331   const int *nodalI=_nodal_connec_index->getConstPointer();
7332   const double *coor=_coords->getConstPointer();
7333   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7334     {
7335       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7336       std::fill(ptToFill,ptToFill+spaceDim,0.);
7337       if(type!=INTERP_KERNEL::NORM_POLYHED)
7338         {
7339           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7340             {
7341               if(*conn>=0 && *conn<nbOfNodes)
7342                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7343               else
7344                 {
7345                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7346                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7347                 }
7348             }
7349           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7350           if(nbOfNodesInCell>0)
7351             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7352           else
7353             {
7354               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7355               throw INTERP_KERNEL::Exception(oss.str().c_str());
7356             }
7357         }
7358       else
7359         {
7360           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7361           s.erase(-1);
7362           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7363             {
7364               if(*it>=0 && *it<nbOfNodes)
7365                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7366               else
7367                 {
7368                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7369                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7370                 }
7371             }
7372           if(!s.empty())
7373             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7374           else
7375             {
7376               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7377               throw INTERP_KERNEL::Exception(oss.str().c_str());
7378             }
7379         }
7380     }
7381   return ret.retn();
7382 }
7383
7384 /*!
7385  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7386  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7387  * are specified via an array of cell ids. 
7388  *  \warning Validity of the specified cell ids is not checked! 
7389  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7390  *  \param [in] begin - an array of cell ids of interest.
7391  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7392  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7393  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7394  *          caller is to delete this array using decrRef() as it is no more needed. 
7395  *  \throw If the coordinates array is not set.
7396  *  \throw If the nodal connectivity of cells is not defined.
7397  *
7398  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7399  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7400  */
7401 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7402 {
7403   DataArrayDouble *ret=DataArrayDouble::New();
7404   int spaceDim=getSpaceDimension();
7405   int nbOfTuple=(int)std::distance(begin,end);
7406   ret->alloc(nbOfTuple,spaceDim);
7407   double *ptToFill=ret->getPointer();
7408   double *tmp=new double[spaceDim];
7409   const int *nodal=_nodal_connec->getConstPointer();
7410   const int *nodalI=_nodal_connec_index->getConstPointer();
7411   const double *coor=_coords->getConstPointer();
7412   for(const int *w=begin;w!=end;w++)
7413     {
7414       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7415       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7416       ptToFill+=spaceDim;
7417     }
7418   delete [] tmp;
7419   return ret;
7420 }
7421
7422 /*!
7423  * Returns a DataArrayDouble instance giving for each cell in \a this the equation of plane given by "a*X+b*Y+c*Z+d=0".
7424  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7425  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7426  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7427  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7428  * 
7429  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7430  * \throw If spaceDim!=3 or meshDim!=2.
7431  * \throw If connectivity of \a this is invalid.
7432  * \throw If connectivity of a cell in \a this points to an invalid node.
7433  */
7434 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7435 {
7436   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7437   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7438   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7439     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7440   ret->alloc(nbOfCells,4);
7441   double *retPtr(ret->getPointer());
7442   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7443   const double *coor(_coords->begin());
7444   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7445     {
7446       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7447       if(nodalI[1]-nodalI[0]>=3)
7448         {
7449           for(int j=0;j<3;j++)
7450             {
7451               int nodeId(nodal[nodalI[0]+1+j]);
7452               if(nodeId>=0 && nodeId<nbOfNodes)
7453                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7454               else
7455                 {
7456                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7457                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7458                 }
7459             }
7460         }
7461       else
7462         {
7463           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7464           throw INTERP_KERNEL::Exception(oss.str().c_str());
7465         }
7466       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7467       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7468     }
7469   return ret.retn();
7470 }
7471
7472 /*!
7473  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7474  * 
7475  */
7476 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7477 {
7478   if(!da)
7479     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7480   da->checkAllocated();
7481   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7482   ret->setCoords(da);
7483   int nbOfTuples=da->getNumberOfTuples();
7484   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7485   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7486   c->alloc(2*nbOfTuples,1);
7487   cI->alloc(nbOfTuples+1,1);
7488   int *cp=c->getPointer();
7489   int *cip=cI->getPointer();
7490   *cip++=0;
7491   for(int i=0;i<nbOfTuples;i++)
7492     {
7493       *cp++=INTERP_KERNEL::NORM_POINT1;
7494       *cp++=i;
7495       *cip++=2*(i+1);
7496     }
7497   ret->setConnectivity(c,cI,true);
7498   return ret.retn();
7499 }
7500 /*!
7501  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7502  * Cells and nodes of
7503  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7504  *  \param [in] mesh1 - the first mesh.
7505  *  \param [in] mesh2 - the second mesh.
7506  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7507  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7508  *          is no more needed.
7509  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7510  *  \throw If the coordinates array is not set in none of the meshes.
7511  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7512  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7513  */
7514 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7515 {
7516   std::vector<const MEDCouplingUMesh *> tmp(2);
7517   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7518   return MergeUMeshes(tmp);
7519 }
7520
7521 /*!
7522  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7523  * Cells and nodes of
7524  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7525  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7526  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7527  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7528  *          is no more needed.
7529  *  \throw If \a a.size() == 0.
7530  *  \throw If \a a[ *i* ] == NULL.
7531  *  \throw If the coordinates array is not set in none of the meshes.
7532  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7533  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7534 */
7535 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7536 {
7537   std::size_t sz=a.size();
7538   if(sz==0)
7539     return MergeUMeshesLL(a);
7540   for(std::size_t ii=0;ii<sz;ii++)
7541     if(!a[ii])
7542       {
7543         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7544         throw INTERP_KERNEL::Exception(oss.str().c_str());
7545       }
7546   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7547   std::vector< const MEDCouplingUMesh * > aa(sz);
7548   int spaceDim=-3;
7549   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7550     {
7551       const MEDCouplingUMesh *cur=a[i];
7552       const DataArrayDouble *coo=cur->getCoords();
7553       if(coo)
7554         spaceDim=coo->getNumberOfComponents();
7555     }
7556   if(spaceDim==-3)
7557     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7558   for(std::size_t i=0;i<sz;i++)
7559     {
7560       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7561       aa[i]=bb[i];
7562     }
7563   return MergeUMeshesLL(aa);
7564 }
7565
7566 /// @cond INTERNAL
7567
7568 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7569 {
7570   if(a.empty())
7571     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7572   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7573   int meshDim=(*it)->getMeshDimension();
7574   int nbOfCells=(*it)->getNumberOfCells();
7575   int meshLgth=(*it++)->getMeshLength();
7576   for(;it!=a.end();it++)
7577     {
7578       if(meshDim!=(*it)->getMeshDimension())
7579         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7580       nbOfCells+=(*it)->getNumberOfCells();
7581       meshLgth+=(*it)->getMeshLength();
7582     }
7583   std::vector<const MEDCouplingPointSet *> aps(a.size());
7584   std::copy(a.begin(),a.end(),aps.begin());
7585   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7586   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7587   ret->setCoords(pts);
7588   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7589   c->alloc(meshLgth,1);
7590   int *cPtr=c->getPointer();
7591   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7592   cI->alloc(nbOfCells+1,1);
7593   int *cIPtr=cI->getPointer();
7594   *cIPtr++=0;
7595   int offset=0;
7596   int offset2=0;
7597   for(it=a.begin();it!=a.end();it++)
7598     {
7599       int curNbOfCell=(*it)->getNumberOfCells();
7600       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7601       const int *curC=(*it)->_nodal_connec->getConstPointer();
7602       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7603       for(int j=0;j<curNbOfCell;j++)
7604         {
7605           const int *src=curC+curCI[j];
7606           *cPtr++=*src++;
7607           for(;src!=curC+curCI[j+1];src++,cPtr++)
7608             {
7609               if(*src!=-1)
7610                 *cPtr=*src+offset2;
7611               else
7612                 *cPtr=-1;
7613             }
7614         }
7615       offset+=curCI[curNbOfCell];
7616       offset2+=(*it)->getNumberOfNodes();
7617     }
7618   //
7619   ret->setConnectivity(c,cI,true);
7620   return ret.retn();
7621 }
7622
7623 /// @endcond
7624
7625 /*!
7626  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7627  * dimension and sharing the node coordinates array.
7628  * All cells of the first mesh precede all cells of the second mesh
7629  * within the result mesh. 
7630  *  \param [in] mesh1 - the first mesh.
7631  *  \param [in] mesh2 - the second mesh.
7632  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7633  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7634  *          is no more needed.
7635  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7636  *  \throw If the meshes do not share the node coordinates array.
7637  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7638  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7639  */
7640 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7641 {
7642   std::vector<const MEDCouplingUMesh *> tmp(2);
7643   tmp[0]=mesh1; tmp[1]=mesh2;
7644   return MergeUMeshesOnSameCoords(tmp);
7645 }
7646
7647 /*!
7648  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7649  * dimension and sharing the node coordinates array.
7650  * All cells of the *i*-th mesh precede all cells of the
7651  * (*i*+1)-th mesh within the result mesh.
7652  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7653  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7654  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7655  *          is no more needed.
7656  *  \throw If \a a.size() == 0.
7657  *  \throw If \a a[ *i* ] == NULL.
7658  *  \throw If the meshes do not share the node coordinates array.
7659  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7660  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7661  */
7662 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7663 {
7664   if(meshes.empty())
7665     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7666   for(std::size_t ii=0;ii<meshes.size();ii++)
7667     if(!meshes[ii])
7668       {
7669         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7670         throw INTERP_KERNEL::Exception(oss.str().c_str());
7671       }
7672   const DataArrayDouble *coords=meshes.front()->getCoords();
7673   int meshDim=meshes.front()->getMeshDimension();
7674   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7675   int meshLgth=0;
7676   int meshIndexLgth=0;
7677   for(;iter!=meshes.end();iter++)
7678     {
7679       if(coords!=(*iter)->getCoords())
7680         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7681       if(meshDim!=(*iter)->getMeshDimension())
7682         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7683       meshLgth+=(*iter)->getMeshLength();
7684       meshIndexLgth+=(*iter)->getNumberOfCells();
7685     }
7686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7687   nodal->alloc(meshLgth,1);
7688   int *nodalPtr=nodal->getPointer();
7689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7690   nodalIndex->alloc(meshIndexLgth+1,1);
7691   int *nodalIndexPtr=nodalIndex->getPointer();
7692   int offset=0;
7693   for(iter=meshes.begin();iter!=meshes.end();iter++)
7694     {
7695       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7696       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7697       int nbOfCells=(*iter)->getNumberOfCells();
7698       int meshLgth2=(*iter)->getMeshLength();
7699       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7700       if(iter!=meshes.begin())
7701         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7702       else
7703         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7704       offset+=meshLgth2;
7705     }
7706   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7707   ret->setName("merge");
7708   ret->setMeshDimension(meshDim);
7709   ret->setConnectivity(nodal,nodalIndex,true);
7710   ret->setCoords(coords);
7711   return ret;
7712 }
7713
7714 /*!
7715  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7716  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7717  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7718  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7719  * New" mode are returned for each input mesh.
7720  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7721  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7722  *          valid values [0,1,2], see zipConnectivityTraducer().
7723  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7724  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7725  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7726  *          no more needed.
7727  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7728  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7729  *          is no more needed.
7730  *  \throw If \a meshes.size() == 0.
7731  *  \throw If \a meshes[ *i* ] == NULL.
7732  *  \throw If the meshes do not share the node coordinates array.
7733  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7734  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7735  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7736  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7737  */
7738 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7739 {
7740   //All checks are delegated to MergeUMeshesOnSameCoords
7741   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7742   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7743   corr.resize(meshes.size());
7744   std::size_t nbOfMeshes=meshes.size();
7745   int offset=0;
7746   const int *o2nPtr=o2n->getConstPointer();
7747   for(std::size_t i=0;i<nbOfMeshes;i++)
7748     {
7749       DataArrayInt *tmp=DataArrayInt::New();
7750       int curNbOfCells=meshes[i]->getNumberOfCells();
7751       tmp->alloc(curNbOfCells,1);
7752       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7753       offset+=curNbOfCells;
7754       tmp->setName(meshes[i]->getName());
7755       corr[i]=tmp;
7756     }
7757   return ret.retn();
7758 }
7759
7760 /*!
7761  * Makes all given meshes share the nodal connectivity array. The common connectivity
7762  * array is created by concatenating the connectivity arrays of all given meshes. All
7763  * the given meshes must be of the same space dimension but dimension of cells **can
7764  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7765  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7766  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7767  *  \param [in,out] meshes - a vector of meshes to update.
7768  *  \throw If any of \a meshes is NULL.
7769  *  \throw If the coordinates array is not set in any of \a meshes.
7770  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7771  *  \throw If \a meshes are of different space dimension.
7772  */
7773 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7774 {
7775   std::size_t sz=meshes.size();
7776   if(sz==0 || sz==1)
7777     return;
7778   std::vector< const DataArrayDouble * > coords(meshes.size());
7779   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7780   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7781     {
7782       if((*it))
7783         {
7784           (*it)->checkConnectivityFullyDefined();
7785           const DataArrayDouble *coo=(*it)->getCoords();
7786           if(coo)
7787             *it2=coo;
7788           else
7789             {
7790               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7791               oss << " has no coordinate array defined !";
7792               throw INTERP_KERNEL::Exception(oss.str().c_str());
7793             }
7794         }
7795       else
7796         {
7797           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7798           oss << " is null !";
7799           throw INTERP_KERNEL::Exception(oss.str().c_str());
7800         }
7801     }
7802   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7803   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7804   int offset=(*it)->getNumberOfNodes();
7805   (*it++)->setCoords(res);
7806   for(;it!=meshes.end();it++)
7807     {
7808       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7809       (*it)->setCoords(res);
7810       (*it)->shiftNodeNumbersInConn(offset);
7811       offset+=oldNumberOfNodes;
7812     }
7813 }
7814
7815 /*!
7816  * Merges nodes coincident with a given precision within all given meshes that share
7817  * the nodal connectivity array. The given meshes **can be of different** mesh
7818  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7819  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7820  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7821  *  \param [in,out] meshes - a vector of meshes to update.
7822  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7823  *  \throw If any of \a meshes is NULL.
7824  *  \throw If the \a meshes do not share the same node coordinates array.
7825  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7826  */
7827 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7828 {
7829   if(meshes.empty())
7830     return ;
7831   std::set<const DataArrayDouble *> s;
7832   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7833     {
7834       if(*it)
7835         s.insert((*it)->getCoords());
7836       else
7837         {
7838           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 !";
7839           throw INTERP_KERNEL::Exception(oss.str().c_str());
7840         }
7841     }
7842   if(s.size()!=1)
7843     {
7844       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 !";
7845       throw INTERP_KERNEL::Exception(oss.str().c_str());
7846     }
7847   const DataArrayDouble *coo=*(s.begin());
7848   if(!coo)
7849     return;
7850   //
7851   DataArrayInt *comm,*commI;
7852   coo->findCommonTuples(eps,-1,comm,commI);
7853   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7854   int oldNbOfNodes=coo->getNumberOfTuples();
7855   int newNbOfNodes;
7856   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7857   if(oldNbOfNodes==newNbOfNodes)
7858     return ;
7859   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7860   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7861     {
7862       (*it)->renumberNodesInConn(o2n->getConstPointer());
7863       (*it)->setCoords(newCoords);
7864     } 
7865 }
7866
7867 /*!
7868  * 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.
7869  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7870  * \param isQuad specifies the policy of connectivity.
7871  * @ret in/out parameter in which the result will be append
7872  */
7873 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7874 {
7875   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7876   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7877   ret.push_back(cm.getExtrudedType());
7878   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7879   switch(flatType)
7880     {
7881     case INTERP_KERNEL::NORM_POINT1:
7882       {
7883         ret.push_back(connBg[1]);
7884         ret.push_back(connBg[1]+nbOfNodesPerLev);
7885         break;
7886       }
7887     case INTERP_KERNEL::NORM_SEG2:
7888       {
7889         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7890         ret.insert(ret.end(),conn,conn+4);
7891         break;
7892       }
7893     case INTERP_KERNEL::NORM_SEG3:
7894       {
7895         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7896         ret.insert(ret.end(),conn,conn+8);
7897         break;
7898       }
7899     case INTERP_KERNEL::NORM_QUAD4:
7900       {
7901         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7902         ret.insert(ret.end(),conn,conn+8);
7903         break;
7904       }
7905     case INTERP_KERNEL::NORM_TRI3:
7906       {
7907         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7908         ret.insert(ret.end(),conn,conn+6);
7909         break;
7910       }
7911     case INTERP_KERNEL::NORM_TRI6:
7912       {
7913         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,
7914                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7915         ret.insert(ret.end(),conn,conn+15);
7916         break;
7917       }
7918     case INTERP_KERNEL::NORM_QUAD8:
7919       {
7920         int conn[20]={
7921           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7922           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7923           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7924         };
7925         ret.insert(ret.end(),conn,conn+20);
7926         break;
7927       }
7928     case INTERP_KERNEL::NORM_POLYGON:
7929       {
7930         std::back_insert_iterator< std::vector<int> > ii(ret);
7931         std::copy(connBg+1,connEnd,ii);
7932         *ii++=-1;
7933         std::reverse_iterator<const int *> rConnBg(connEnd);
7934         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7935         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7936         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7937         for(std::size_t i=0;i<nbOfRadFaces;i++)
7938           {
7939             *ii++=-1;
7940             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7941             std::copy(conn,conn+4,ii);
7942           }
7943         break;
7944       }
7945     default:
7946       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7947     }
7948 }
7949
7950 /*!
7951  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7952  */
7953 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7954 {
7955   std::size_t i, ip1;
7956   double v[3]={0.,0.,0.};
7957   std::size_t sz=std::distance(begin,end);
7958   if(isQuadratic)
7959     sz/=2;
7960   for(i=0;i<sz;i++)
7961     {
7962       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];
7963       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7964       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7965     }
7966   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7967
7968   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
7969   // SEG3 forming a circle):
7970   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
7971     {
7972       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
7973       for(std::size_t j=0;j<sz;j++)
7974         {
7975           if (j%2)  // current point i is quadratic, next point i+1 is standard
7976             {
7977               i = sz+j;
7978               ip1 = (j+1)%sz; // ip1 = "i+1"
7979             }
7980           else      // current point i is standard, next point i+1 is quadratic
7981             {
7982               i = j;
7983               ip1 = j+sz;
7984             }
7985           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
7986           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
7987           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
7988         }
7989       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7990     }
7991   return (ret>0.);
7992 }
7993
7994 /*!
7995  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7996  */
7997 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7998 {
7999   std::vector<std::pair<int,int> > edges;
8000   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8001   const int *bgFace=begin;
8002   for(std::size_t i=0;i<nbOfFaces;i++)
8003     {
8004       const int *endFace=std::find(bgFace+1,end,-1);
8005       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8006       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8007         {
8008           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8009           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8010             return false;
8011           edges.push_back(p1);
8012         }
8013       bgFace=endFace+1;
8014     }
8015   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8016 }
8017
8018 /*!
8019  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8020  */
8021 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8022 {
8023   double vec0[3],vec1[3];
8024   std::size_t sz=std::distance(begin,end);
8025   if(sz%2!=0)
8026     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8027   int nbOfNodes=(int)sz/2;
8028   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8029   const double *pt0=coords+3*begin[0];
8030   const double *pt1=coords+3*begin[nbOfNodes];
8031   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8032   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8033 }
8034
8035 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8036 {
8037   std::size_t sz=std::distance(begin,end);
8038   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8039   std::size_t nbOfNodes(sz/2);
8040   std::copy(begin,end,(int *)tmp);
8041   for(std::size_t j=1;j<nbOfNodes;j++)
8042     {
8043       begin[j]=tmp[nbOfNodes-j];
8044       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8045     }
8046 }
8047
8048 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8049 {
8050   std::size_t sz=std::distance(begin,end);
8051   if(sz!=4)
8052     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8053   double vec0[3],vec1[3];
8054   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8055   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]; 
8056   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;
8057 }
8058
8059 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8060 {
8061   std::size_t sz=std::distance(begin,end);
8062   if(sz!=5)
8063     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8064   double vec0[3];
8065   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8066   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8067   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8068 }
8069
8070 /*!
8071  * 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 ) 
8072  * 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
8073  * a 2D space.
8074  *
8075  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8076  * \param [in] coords the coordinates with nb of components exactly equal to 3
8077  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8078  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8079  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8080  */
8081 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8082 {
8083   int nbFaces=std::count(begin+1,end,-1)+1;
8084   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8085   double *vPtr=v->getPointer();
8086   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8087   double *pPtr=p->getPointer();
8088   const int *stFaceConn=begin+1;
8089   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8090     {
8091       const int *endFaceConn=std::find(stFaceConn,end,-1);
8092       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8093       stFaceConn=endFaceConn+1;
8094     }
8095   pPtr=p->getPointer(); vPtr=v->getPointer();
8096   DataArrayInt *comm1=0,*commI1=0;
8097   v->findCommonTuples(eps,-1,comm1,commI1);
8098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8099   const int *comm1Ptr=comm1->getConstPointer();
8100   const int *commI1Ptr=commI1->getConstPointer();
8101   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8102   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8103   //
8104   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8105   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8106   mm->finishInsertingCells();
8107   //
8108   for(int i=0;i<nbOfGrps1;i++)
8109     {
8110       int vecId=comm1Ptr[commI1Ptr[i]];
8111       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8112       DataArrayInt *comm2=0,*commI2=0;
8113       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8114       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8115       const int *comm2Ptr=comm2->getConstPointer();
8116       const int *commI2Ptr=commI2->getConstPointer();
8117       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8118       for(int j=0;j<nbOfGrps2;j++)
8119         {
8120           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8121             {
8122               res->insertAtTheEnd(begin,end);
8123               res->pushBackSilent(-1);
8124             }
8125           else
8126             {
8127               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8128               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8129               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8130               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8131               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8132               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8133               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8134               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8135               const int *idsNodePtr=idsNode->getConstPointer();
8136               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];
8137               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8138               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8139               if(std::abs(norm)>eps)
8140                 {
8141                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8142                   mm3->rotate(center,vec,angle);
8143                 }
8144               mm3->changeSpaceDimension(2);
8145               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8146               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8147               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8148               int nbOfCells=mm4->getNumberOfCells();
8149               for(int k=0;k<nbOfCells;k++)
8150                 {
8151                   int l=0;
8152                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8153                     res->pushBackSilent(idsNodePtr[*work]);
8154                   res->pushBackSilent(-1);
8155                 }
8156             }
8157         }
8158     }
8159   res->popBackSilent();
8160 }
8161
8162 /*!
8163  * 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
8164  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8165  * 
8166  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8167  * \param [in] coords coordinates expected to have 3 components.
8168  * \param [in] begin start of the nodal connectivity of the face.
8169  * \param [in] end end of the nodal connectivity (excluded) of the face.
8170  * \param [out] v the normalized vector of size 3
8171  * \param [out] p the pos of plane
8172  */
8173 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8174 {
8175   std::size_t nbPoints=std::distance(begin,end);
8176   if(nbPoints<3)
8177     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8178   double vec[3]={0.,0.,0.};
8179   std::size_t j=0;
8180   bool refFound=false;
8181   for(;j<nbPoints-1 && !refFound;j++)
8182     {
8183       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8184       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8185       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8186       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8187       if(norm>eps)
8188         {
8189           refFound=true;
8190           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8191         }
8192     }
8193   for(std::size_t i=j;i<nbPoints-1;i++)
8194     {
8195       double curVec[3];
8196       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8197       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8198       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8199       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8200       if(norm<eps)
8201         continue;
8202       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8203       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];
8204       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8205       if(norm>eps)
8206         {
8207           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8208           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8209           return ;
8210         }
8211     }
8212   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8213 }
8214
8215 /*!
8216  * This method tries to obtain a well oriented polyhedron.
8217  * If the algorithm fails, an exception will be thrown.
8218  */
8219 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8220 {
8221   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8222   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8223   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8224   isPerm[0]=true;
8225   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8226   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8227   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8228   //
8229   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8230     {
8231       bgFace=begin;
8232       std::size_t smthChanged=0;
8233       for(std::size_t i=0;i<nbOfFaces;i++)
8234         {
8235           endFace=std::find(bgFace+1,end,-1);
8236           nbOfEdgesInFace=std::distance(bgFace,endFace);
8237           if(!isPerm[i])
8238             {
8239               bool b;
8240               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8241                 {
8242                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8243                   std::pair<int,int> p2(p1.second,p1.first);
8244                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8245                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8246                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8247                 }
8248               if(isPerm[i])
8249                 { 
8250                   if(!b)
8251                     std::reverse(bgFace+1,endFace);
8252                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8253                     {
8254                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8255                       std::pair<int,int> p2(p1.second,p1.first);
8256                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8257                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8258                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8259                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8260                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8261                       if(it!=edgesOK.end())
8262                         {
8263                           edgesOK.erase(it);
8264                           edgesFinished.push_back(p1);
8265                         }
8266                       else
8267                         edgesOK.push_back(p1);
8268                     }
8269                 }
8270             }
8271           bgFace=endFace+1;
8272         }
8273       if(smthChanged==0)
8274         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8275     }
8276   if(!edgesOK.empty())
8277     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8278   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8279     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8280       bgFace=begin;
8281       for(std::size_t i=0;i<nbOfFaces;i++)
8282         {
8283           endFace=std::find(bgFace+1,end,-1);
8284           std::reverse(bgFace+1,endFace);
8285           bgFace=endFace+1;
8286         }
8287     }
8288 }
8289
8290 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8291 {
8292   int nbOfNodesExpected(skin->getNumberOfNodes());
8293   const int *n2oPtr(n2o->getConstPointer());
8294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8295   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8296   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8297   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8298   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8300   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8301   if(nbOfNodesExpected<1)
8302     return ret.retn();
8303   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8304   *work++=n2oPtr[prevNode];
8305   for(int i=1;i<nbOfNodesExpected;i++)
8306     {
8307       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8308         {
8309           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8310           conn.erase(prevNode);
8311           if(conn.size()==1)
8312             {
8313               int curNode(*(conn.begin()));
8314               *work++=n2oPtr[curNode];
8315               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8316               shar.erase(prevCell);
8317               if(shar.size()==1)
8318                 {
8319                   prevCell=*(shar.begin());
8320                   prevNode=curNode;
8321                 }
8322               else
8323                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8324             }
8325           else
8326             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8327         }
8328       else
8329         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8330     }
8331   return ret.retn();
8332 }
8333
8334 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8335 {
8336   int nbOfNodesExpected(skin->getNumberOfNodes());
8337   int nbOfTurn(nbOfNodesExpected/2);
8338   const int *n2oPtr(n2o->getConstPointer());
8339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8340   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8341   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8342   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8343   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8345   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8346   if(nbOfNodesExpected<1)
8347     return ret.retn();
8348   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8349   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8350   for(int i=1;i<nbOfTurn;i++)
8351     {
8352       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8353         {
8354           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8355           conn.erase(prevNode);
8356           if(conn.size()==1)
8357             {
8358               int curNode(*(conn.begin()));
8359               *work=n2oPtr[curNode];
8360               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8361               shar.erase(prevCell);
8362               if(shar.size()==1)
8363                 {
8364                   int curCell(*(shar.begin()));
8365                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8366                   prevCell=curCell;
8367                   prevNode=curNode;
8368                   work++;
8369                 }
8370               else
8371                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8372             }
8373           else
8374             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8375         }
8376       else
8377         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8378     }
8379   return ret.retn();
8380 }
8381
8382 /*!
8383  * This method makes the assumption spacedimension == meshdimension == 2.
8384  * This method works only for linear cells.
8385  * 
8386  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8387  */
8388 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8389 {
8390   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8391     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8392   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8393   int oldNbOfNodes(skin->getNumberOfNodes());
8394   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8395   int nbOfNodesExpected(skin->getNumberOfNodes());
8396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8397   int nbCells(skin->getNumberOfCells());
8398   if(nbCells==nbOfNodesExpected)
8399     return buildUnionOf2DMeshLinear(skin,n2o);
8400   else if(2*nbCells==nbOfNodesExpected)
8401     return buildUnionOf2DMeshQuadratic(skin,n2o);
8402   else
8403     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8404 }
8405
8406 /*!
8407  * This method makes the assumption spacedimension == meshdimension == 3.
8408  * This method works only for linear cells.
8409  * 
8410  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8411  */
8412 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8413 {
8414   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8415     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8416   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8417   const int *conn=m->getNodalConnectivity()->getConstPointer();
8418   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8419   int nbOfCells=m->getNumberOfCells();
8420   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8421   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8422   if(nbOfCells<1)
8423     return ret.retn();
8424   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8425   for(int i=1;i<nbOfCells;i++)
8426     {
8427       *work++=-1;
8428       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8429     }
8430   return ret.retn();
8431 }
8432
8433 /*!
8434  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8435  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8436  */
8437 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8438 {
8439   double *w=zipFrmt;
8440   if(spaceDim==3)
8441     for(int i=0;i<nbOfNodesInCell;i++)
8442       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8443   else if(spaceDim==2)
8444     {
8445       for(int i=0;i<nbOfNodesInCell;i++)
8446         {
8447           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8448           *w++=0.;
8449         }
8450     }
8451   else
8452     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8453 }
8454
8455 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8456 {
8457   int nbOfCells=getNumberOfCells();
8458   if(nbOfCells<=0)
8459     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8460   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,36,4};
8461   ofs << "  <" << getVTKDataSetType() << ">\n";
8462   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8463   ofs << "      <PointData>\n" << pointData << std::endl;
8464   ofs << "      </PointData>\n";
8465   ofs << "      <CellData>\n" << cellData << std::endl;
8466   ofs << "      </CellData>\n";
8467   ofs << "      <Points>\n";
8468   if(getSpaceDimension()==3)
8469     _coords->writeVTK(ofs,8,"Points",byteData);
8470   else
8471     {
8472       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8473       coo->writeVTK(ofs,8,"Points",byteData);
8474     }
8475   ofs << "      </Points>\n";
8476   ofs << "      <Cells>\n";
8477   const int *cPtr=_nodal_connec->getConstPointer();
8478   const int *cIPtr=_nodal_connec_index->getConstPointer();
8479   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8481   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8482   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8483   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8484   int szFaceOffsets=0,szConn=0;
8485   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8486     {
8487       *w2=cPtr[cIPtr[i]];
8488       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8489         {
8490           *w1=-1;
8491           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8492           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8493         }
8494       else
8495         {
8496           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8497           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8498           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8499           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8500           w4=std::copy(c.begin(),c.end(),w4);
8501         }
8502     }
8503   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8504   types->writeVTK(ofs,8,"UInt8","types",byteData);
8505   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8506   if(szFaceOffsets!=0)
8507     {//presence of Polyhedra
8508       connectivity->reAlloc(szConn);
8509       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8510       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8511       w1=faces->getPointer();
8512       for(int i=0;i<nbOfCells;i++)
8513         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8514           {
8515             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8516             *w1++=nbFaces;
8517             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8518             for(int j=0;j<nbFaces;j++)
8519               {
8520                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8521                 *w1++=(int)std::distance(w6,w5);
8522                 w1=std::copy(w6,w5,w1);
8523                 w6=w5+1;
8524               }
8525           }
8526       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8527     }
8528   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8529   ofs << "      </Cells>\n";
8530   ofs << "    </Piece>\n";
8531   ofs << "  </" << getVTKDataSetType() << ">\n";
8532 }
8533
8534 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8535 {
8536   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8537   if(_mesh_dim==-2)
8538     { stream << " Not set !"; return ; }
8539   stream << " Mesh dimension : " << _mesh_dim << ".";
8540   if(_mesh_dim==-1)
8541     return ;
8542   if(!_coords)
8543     { stream << " No coordinates set !"; return ; }
8544   if(!_coords->isAllocated())
8545     { stream << " Coordinates set but not allocated !"; return ; }
8546   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8547   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8548   if(!_nodal_connec_index)
8549     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8550   if(!_nodal_connec_index->isAllocated())
8551     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8552   int lgth=_nodal_connec_index->getNumberOfTuples();
8553   int cpt=_nodal_connec_index->getNumberOfComponents();
8554   if(cpt!=1 || lgth<1)
8555     return ;
8556   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8557 }
8558
8559 std::string MEDCouplingUMesh::getVTKDataSetType() const
8560 {
8561   return std::string("UnstructuredGrid");
8562 }
8563
8564 /*!
8565  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8566  * returns a result mesh constituted by polygons.
8567  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8568  * all nodes from m2.
8569  * The meshes should be in 2D space. In
8570  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8571  * meshes.
8572  *  \param [in] m1 - the first input mesh which is a partitioned object.
8573  *  \param [in] m2 - the second input mesh which is a partition tool.
8574  *  \param [in] eps - precision used to detect coincident mesh entities.
8575  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8576  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8577  *         this array using decrRef() as it is no more needed.
8578  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8579  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8580  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8581  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8582  *         it is no more needed.  
8583  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8584  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8585  *         is no more needed.  
8586  *  \throw If the coordinates array is not set in any of the meshes.
8587  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8588  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8589  */
8590 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8591                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8592 {
8593   m1->checkFullyDefined();
8594   m2->checkFullyDefined();
8595   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8596     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8597
8598   // Step 1: compute all edge intersections (new nodes)
8599   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8600   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8601   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8602   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8603   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8604   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8605   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8606                                       m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8607                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8608   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8609   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8610   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8611
8612   // Step 2: re-order newly created nodes according to the ordering found in m2
8613   std::vector< std::vector<int> > intersectEdge2;
8614   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8615   subDiv2.clear(); dd5=0; dd6=0;
8616
8617   // Step 3:
8618   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8619   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8620   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8621                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8622
8623   // Step 4: Prepare final result:
8624   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8625   addCooDa->alloc((int)(addCoo.size())/2,2);
8626   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8627   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8628   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8629   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8630   std::vector<const DataArrayDouble *> coordss(4);
8631   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8632   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8633   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8634   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8635   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8637   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8638   ret->setConnectivity(conn,connI,true);
8639   ret->setCoords(coo);
8640   cellNb1=c1.retn(); cellNb2=c2.retn();
8641   return ret.retn();
8642 }
8643
8644
8645 /**
8646  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8647  * (newly created) nodes corresponding to the edge intersections.
8648  * Output params:
8649  * @param[out] cr, crI connectivity of the resulting mesh
8650  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8651  * TODO: describe input parameters
8652  */
8653 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8654                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8655                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8656                                                          const std::vector<double>& addCoords,
8657                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8658 {
8659   static const int SPACEDIM=2;
8660   const double *coo1=m1->getCoords()->getConstPointer();
8661   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8662   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8663   int offset1=m1->getNumberOfNodes();
8664   const double *coo2=m2->getCoords()->getConstPointer();
8665   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8666   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8667   int offset2=offset1+m2->getNumberOfNodes();
8668   int offset3=offset2+((int)addCoords.size())/2;
8669   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8670   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8671   // Here a BBTree on 2D-cells, not on segments:
8672   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8673   int ncell1=m1->getNumberOfCells();
8674   crI.push_back(0);
8675   for(int i=0;i<ncell1;i++)
8676     {
8677       std::vector<int> candidates2;
8678       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8679       std::map<INTERP_KERNEL::Node *,int> mapp;
8680       std::map<int,INTERP_KERNEL::Node *> mappRev;
8681       INTERP_KERNEL::QuadraticPolygon pol1;
8682       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8683       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8684       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8685       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8686       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8687       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8688                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8689       //
8690       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
8691       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8692       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8693       for(it1.first();!it1.finished();it1.next())
8694         edges1.insert(it1.current()->getPtr());
8695       //
8696       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8697       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8698       int ii=0;
8699       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8700         {
8701           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8702           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8703           // Complete mapping with elements coming from the current cell it2 in mesh2:
8704           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8705           // pol2 is the new QP in the final merged result.
8706           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8707                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8708         }
8709       ii=0;
8710       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8711         {
8712           pol1.initLocationsWithOther(pol2s[ii]);
8713           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8714           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8715           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8716         }
8717       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8718       // by m2 but that we still want to keep in the final result.
8719       if(!edges1.empty())
8720         {
8721           try
8722             {
8723               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8724             }
8725           catch(INTERP_KERNEL::Exception& e)
8726             {
8727               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();
8728               throw INTERP_KERNEL::Exception(oss.str().c_str());
8729             }
8730         }
8731       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8732         (*it).second->decrRef();
8733     }
8734 }
8735
8736 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8737 {
8738   std::map<INTERP_KERNEL::Node *,int>::const_iterator it(m.find(n));
8739   if(it==m.end())
8740     throw INTERP_KERNEL::Exception("Internal error in remapping !");
8741   int v((*it).second);
8742   if(v==forbVal0 || v==forbVal1)
8743     return ;
8744   if(std::find(isect.begin(),isect.end(),v)==isect.end())
8745     isect.push_back(v);
8746 }
8747
8748 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8749 {
8750   int sz(c.size());
8751   if(sz<=1)
8752     return false;
8753   bool presenceOfOn(false);
8754   for(int i=0;i<sz;i++)
8755     {
8756       INTERP_KERNEL::ElementaryEdge *e(c[i]);
8757       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
8758         continue ;
8759       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
8760       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
8761     }
8762   return presenceOfOn;
8763 }
8764
8765 /**
8766  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
8767  * To do the work this method can optionnaly needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
8768  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
8769  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
8770  *
8771  * \return int - the number of new nodes created (in most of cases 0).
8772  * 
8773  * \throw If \a this is not coherent.
8774  * \throw If \a this has not spaceDim equal to 2.
8775  * \throw If \a this has not meshDim equal to 2.
8776  * \throw If some subcells needed to be split are orphan.
8777  * \sa MEDCouplingUMesh::conformize2D
8778  */
8779 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
8780 {
8781   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
8782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
8783   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
8784   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8786   if(midOpt==0 && midOptI==0)
8787     {
8788       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
8789       return 0;
8790     }
8791   else if(midOpt!=0 && midOptI!=0)
8792     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
8793   else
8794     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
8795 }
8796
8797 /*!
8798  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
8799  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
8800  * This method performs a conformization of \b this. So if a edge in \a this can be split into entire edges in \a this this method
8801  * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges have same nature each other (Linear,Quadratic).
8802  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
8803  * The modified cells if any are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the 
8804  *
8805  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
8806  * This method expects that all nodes in \a this are not closer than \a eps.
8807  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
8808  * 
8809  * \param [in] eps the relative error to detect merged edges.
8810  * \return DataArrayInt  * - The list of cellIds in \a this that have been subdivided. If empty, nothing changed in \a this (as if it were a const method). The array is a newly allocated array
8811  *                           that the user is expected to deal with.
8812  *
8813  * \throw If \a this is not coherent.
8814  * \throw If \a this has not spaceDim equal to 2.
8815  * \throw If \a this has not meshDim equal to 2.
8816  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
8817  */
8818 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
8819 {
8820   static const int SPACEDIM=2;
8821   checkCoherency();
8822   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8823     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8824   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
8825   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
8826   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
8827   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
8828   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
8829   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
8830   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
8831   std::vector<double> addCoo;
8832   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
8833   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8834   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8835   for(int i=0;i<nDescCell;i++)
8836     {
8837       std::vector<int> candidates;
8838       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
8839       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8840         if(*it>i)
8841           {
8842             std::map<INTERP_KERNEL::Node *,int> m;
8843             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
8844               *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
8845             INTERP_KERNEL::MergePoints merge;
8846             INTERP_KERNEL::QuadraticPolygon c1,c2;
8847             e1->intersectWith(e2,merge,c1,c2);
8848             e1->decrRef(); e2->decrRef();
8849             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
8850               overlapEdge[i].push_back(*it);
8851             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
8852               overlapEdge[*it].push_back(i);
8853             for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8854               (*it2).first->decrRef();
8855           }
8856     }
8857   // splitting done. sort intersect point in intersectEdge.
8858   std::vector< std::vector<int> > middle(nDescCell);
8859   int nbOf2DCellsToBeSplit(0);
8860   bool middleNeedsToBeUsed(false);
8861   std::vector<bool> cells2DToTreat(nDescCell,false);
8862   for(int i=0;i<nDescCell;i++)
8863     {
8864       std::vector<int>& isect(intersectEdge[i]);
8865       int sz((int)isect.size());
8866       if(sz>1)
8867         {
8868           std::map<INTERP_KERNEL::Node *,int> m;
8869           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
8870           e->sortSubNodesAbs(coords,isect);
8871           e->decrRef();
8872           for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8873             (*it2).first->decrRef();
8874         }
8875       if(sz!=0)
8876         {
8877           int idx0(rdi[i]),idx1(rdi[i+1]);
8878           if(idx1-idx0!=1)
8879             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
8880           if(!cells2DToTreat[rd[idx0]])
8881             {
8882               cells2DToTreat[rd[idx0]]=true;
8883               nbOf2DCellsToBeSplit++;
8884             }
8885           // try to reuse at most eventual 'middle' of SEG3
8886           std::vector<int>& mid(middle[i]);
8887           mid.resize(sz+1,-1);
8888           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
8889             {
8890               middleNeedsToBeUsed=true;
8891               const std::vector<int>& candidates(overlapEdge[i]);
8892               std::vector<int> trueCandidates;
8893               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
8894                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
8895                   trueCandidates.push_back(*itc);
8896               int stNode(c[ci[i]+1]),endNode(isect[0]);
8897               for(int j=0;j<sz+1;j++)
8898                 {
8899                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
8900                     {
8901                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
8902                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
8903                         { mid[j]=*itc; break; }
8904                     }
8905                   stNode=endNode;
8906                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
8907                 }
8908             }
8909         }
8910     }
8911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
8912   if(nbOf2DCellsToBeSplit==0)
8913     return ret.retn();
8914   //
8915   int *retPtr(ret->getPointer());
8916   for(int i=0;i<nCell;i++)
8917     if(cells2DToTreat[i])
8918       *retPtr++=i;
8919   //
8920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
8921   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
8922   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
8923   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
8924   if(middleNeedsToBeUsed)
8925     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
8926   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
8927   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
8928   setCoords(modif->getCoords());//if nbOfNodesCreated==0 modif and this have the same coordinates pointer so this line has no effect. But for quadratic cases this line is important.
8929   setPartOfMySelf(ret->begin(),ret->end(),*modif);
8930   {
8931     bool areNodesMerged; int newNbOfNodes;
8932     if(nbOfNodesCreated!=0)
8933       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
8934   }
8935   return ret.retn();
8936 }
8937
8938 /*!
8939  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8940  * It builds the descending connectivity of the two meshes, and then using a binary tree
8941  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
8942  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
8943  */
8944 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8945                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8946                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8947                                                    std::vector<double>& addCoo,
8948                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
8949                                                    throw(INTERP_KERNEL::Exception)
8950 {
8951   static const int SPACEDIM=2;
8952   // Build desc connectivity
8953   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8954   desc2=DataArrayInt::New();
8955   descIndx2=DataArrayInt::New();
8956   revDesc2=DataArrayInt::New();
8957   revDescIndx2=DataArrayInt::New();
8958   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8959   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8960   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8961   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8962   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8963   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8964   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8965
8966   // Build BB tree of all edges in the tool mesh (second mesh)
8967   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8968   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8969   int nDescCell1=m1Desc->getNumberOfCells();
8970   int nDescCell2=m2Desc->getNumberOfCells();
8971   intersectEdge1.resize(nDescCell1);
8972   colinear2.resize(nDescCell2);
8973   subDiv2.resize(nDescCell2);
8974   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8975
8976   std::vector<int> candidates1(1);
8977   int offset1=m1->getNumberOfNodes();
8978   int offset2=offset1+m2->getNumberOfNodes();
8979   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
8980     {
8981       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
8982       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8983       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
8984         {
8985           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8986           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
8987           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8988           candidates1[0]=i;
8989           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8990           // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
8991           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
8992           std::set<INTERP_KERNEL::Node *> nodes;
8993           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
8994           std::size_t szz(nodes.size());
8995           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
8996           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
8997           for(std::size_t iii=0;iii<szz;iii++,itt++)
8998             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
8999           // end of protection
9000           // Performs egde cutting:
9001           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
9002           delete pol2;
9003           delete pol1;
9004         }
9005       else
9006         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9007     }
9008   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
9009   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
9010 }
9011
9012 /*!
9013  * This method performs the 2nd step of Partition of 2D mesh.
9014  * This method has 4 inputs :
9015  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
9016  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
9017  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
9018  * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2'
9019  * Nodes end up lying consecutively on a cutted edge.
9020  * \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.
9021  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
9022  * \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.
9023  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
9024  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
9025  */
9026 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9027       const std::vector<double>& addCoo,
9028       const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
9029 {
9030   int offset1=m1->getNumberOfNodes();
9031   int ncell=m2->getNumberOfCells();
9032   const int *c=m2->getNodalConnectivity()->getConstPointer();
9033   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
9034   const double *coo=m2->getCoords()->getConstPointer();
9035   const double *cooBis=m1->getCoords()->getConstPointer();
9036   int offset2=offset1+m2->getNumberOfNodes();
9037   intersectEdge.resize(ncell);
9038   for(int i=0;i<ncell;i++,cI++)
9039     {
9040       const std::vector<int>& divs=subDiv[i];
9041       int nnode=cI[1]-cI[0]-1;
9042       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
9043       std::map<INTERP_KERNEL::Node *, int> mapp22;
9044       for(int j=0;j<nnode;j++)
9045         {
9046           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
9047           int nnid=c[(*cI)+j+1];
9048           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
9049           mapp22[nn]=nnid+offset1;
9050         }
9051       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
9052       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
9053         ((*it).second.first)->decrRef();
9054       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
9055       std::map<INTERP_KERNEL::Node *,int> mapp3;
9056       for(std::size_t j=0;j<divs.size();j++)
9057         {
9058           int id=divs[j];
9059           INTERP_KERNEL::Node *tmp=0;
9060           if(id<offset1)
9061             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
9062           else if(id<offset2)
9063             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
9064           else
9065             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
9066           addNodes[j]=tmp;
9067           mapp3[tmp]=id;
9068         }
9069       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
9070       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
9071         (*it)->decrRef();
9072       e->decrRef();
9073     }
9074 }
9075
9076 /*!
9077  * 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).
9078  * 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
9079  * with a plane. The result will be put in 'cut3DSuf' out parameter.
9080  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
9081  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
9082  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
9083  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
9084  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
9085  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
9086  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
9087  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
9088  * \param [out] cut3DSuf input/output param.
9089  */
9090 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
9091                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
9092                                                    const int *desc, const int *descIndx, 
9093                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
9094 {
9095   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
9096   int nbOf3DSurfCell=(int)cut3DSurf.size();
9097   for(int i=0;i<nbOf3DSurfCell;i++)
9098     {
9099       std::vector<int> res;
9100       int offset=descIndx[i];
9101       int nbOfSeg=descIndx[i+1]-offset;
9102       for(int j=0;j<nbOfSeg;j++)
9103         {
9104           int edgeId=desc[offset+j];
9105           int status=cut3DCurve[edgeId];
9106           if(status!=-2)
9107             {
9108               if(status>-1)
9109                 res.push_back(status);
9110               else
9111                 {
9112                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
9113                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
9114                 }
9115             }
9116         }
9117       switch(res.size())
9118         {
9119         case 2:
9120           {
9121             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9122             break;
9123           }
9124         case 1:
9125         case 0:
9126           {
9127             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
9128             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
9129             if(res.size()==2)
9130               {
9131                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9132               }
9133             else
9134               {
9135                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
9136               }
9137             break;
9138           }
9139         default:
9140           {// case when plane is on a multi colinear edge of a polyhedron
9141             if((int)res.size()==2*nbOfSeg)
9142               {
9143                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
9144               }
9145             else
9146               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
9147           }
9148         }
9149     }
9150 }
9151
9152 /*!
9153  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
9154  * 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).
9155  * 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
9156  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
9157  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
9158  * \param desc is the descending connectivity 3D->3DSurf
9159  * \param descIndx is the descending connectivity index 3D->3DSurf
9160  */
9161 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
9162                                                   const int *desc, const int *descIndx,
9163                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
9164 {
9165   checkFullyDefined();
9166   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9167     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
9168   const int *nodal3D=_nodal_connec->getConstPointer();
9169   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
9170   int nbOfCells=getNumberOfCells();
9171   for(int i=0;i<nbOfCells;i++)
9172     {
9173       std::map<int, std::set<int> > m;
9174       int offset=descIndx[i];
9175       int nbOfFaces=descIndx[i+1]-offset;
9176       int start=-1;
9177       int end=-1;
9178       for(int j=0;j<nbOfFaces;j++)
9179         {
9180           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
9181           if(p.first!=-1 && p.second!=-1)
9182             {
9183               if(p.first!=-2)
9184                 {
9185                   start=p.first; end=p.second;
9186                   m[p.first].insert(p.second);
9187                   m[p.second].insert(p.first);
9188                 }
9189               else
9190                 {
9191                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
9192                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
9193                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
9194                   INTERP_KERNEL::NormalizedCellType cmsId;
9195                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
9196                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
9197                   for(unsigned k=0;k<nbOfNodesSon;k++)
9198                     {
9199                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
9200                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
9201                     }
9202                 }
9203             }
9204         }
9205       if(m.empty())
9206         continue;
9207       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
9208       int prev=end;
9209       while(end!=start)
9210         {
9211           std::map<int, std::set<int> >::const_iterator it=m.find(start);
9212           const std::set<int>& s=(*it).second;
9213           std::set<int> s2; s2.insert(prev);
9214           std::set<int> s3;
9215           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
9216           if(s3.size()==1)
9217             {
9218               int val=*s3.begin();
9219               conn.push_back(start);
9220               prev=start;
9221               start=val;
9222             }
9223           else
9224             start=end;
9225         }
9226       conn.push_back(end);
9227       if(conn.size()>3)
9228         {
9229           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
9230           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
9231           cellIds->pushBackSilent(i);
9232         }
9233     }
9234 }
9235
9236 /*!
9237  * 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
9238  * 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
9239  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9240  * 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
9241  * 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.
9242  * 
9243  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9244  */
9245 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9246 {
9247   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9248   if(sz>=4)
9249     {
9250       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9251       if(cm.getDimension()==2)
9252         {
9253           const int *node=nodalConnBg+1;
9254           int startNode=*node++;
9255           double refX=coords[2*startNode];
9256           for(;node!=nodalConnEnd;node++)
9257             {
9258               if(coords[2*(*node)]<refX)
9259                 {
9260                   startNode=*node;
9261                   refX=coords[2*startNode];
9262                 }
9263             }
9264           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9265           refX=1e300;
9266           double tmp1;
9267           double tmp2[2];
9268           double angle0=-M_PI/2;
9269           //
9270           int nextNode=-1;
9271           int prevNode=-1;
9272           double resRef;
9273           double angleNext=0.;
9274           while(nextNode!=startNode)
9275             {
9276               nextNode=-1;
9277               resRef=1e300;
9278               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9279                 {
9280                   if(*node!=tmpOut.back() && *node!=prevNode)
9281                     {
9282                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9283                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9284                       double res;
9285                       if(angleM<=angle0)
9286                         res=angle0-angleM;
9287                       else
9288                         res=angle0-angleM+2.*M_PI;
9289                       if(res<resRef)
9290                         {
9291                           nextNode=*node;
9292                           resRef=res;
9293                           angleNext=angleM;
9294                         }
9295                     }
9296                 }
9297               if(nextNode!=startNode)
9298                 {
9299                   angle0=angleNext-M_PI;
9300                   if(angle0<-M_PI)
9301                     angle0+=2*M_PI;
9302                   prevNode=tmpOut.back();
9303                   tmpOut.push_back(nextNode);
9304                 }
9305             }
9306           std::vector<int> tmp3(2*(sz-1));
9307           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9308           std::copy(nodalConnBg+1,nodalConnEnd,it);
9309           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9310             {
9311               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9312               return false;
9313             }
9314           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9315             {
9316               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9317               return false;
9318             }
9319           else
9320             {
9321               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9322               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9323               return true;
9324             }
9325         }
9326       else
9327         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9328     }
9329   else
9330     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9331 }
9332
9333 /*!
9334  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9335  * 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.
9336  * 
9337  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9338  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9339  * \param [in,out] arr array in which the remove operation will be done.
9340  * \param [in,out] arrIndx array in the remove operation will modify
9341  * \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])
9342  * \return true if \b arr and \b arrIndx have been modified, false if not.
9343  */
9344 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9345 {
9346   if(!arrIndx || !arr)
9347     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9348   if(offsetForRemoval<0)
9349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9350   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9351   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9352   int *arrIPtr=arrIndx->getPointer();
9353   *arrIPtr++=0;
9354   int previousArrI=0;
9355   const int *arrPtr=arr->getConstPointer();
9356   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9357   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9358     {
9359       if(*arrIPtr-previousArrI>offsetForRemoval)
9360         {
9361           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9362             {
9363               if(s.find(*work)==s.end())
9364                 arrOut.push_back(*work);
9365             }
9366         }
9367       previousArrI=*arrIPtr;
9368       *arrIPtr=(int)arrOut.size();
9369     }
9370   if(arr->getNumberOfTuples()==(int)arrOut.size())
9371     return false;
9372   arr->alloc((int)arrOut.size(),1);
9373   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9374   return true;
9375 }
9376
9377 /*!
9378  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9379  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9380  * The selection of extraction is done standardly in new2old format.
9381  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9382  *
9383  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9384  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9385  * \param [in] arrIn arr origin array from which the extraction will be done.
9386  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9387  * \param [out] arrOut the resulting array
9388  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9389  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9390  */
9391 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9392                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9393 {
9394   if(!arrIn || !arrIndxIn)
9395     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9396   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9397   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9398     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9399   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9400   const int *arrInPtr=arrIn->getConstPointer();
9401   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9402   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9403   if(nbOfGrps<0)
9404     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9405   int maxSizeOfArr=arrIn->getNumberOfTuples();
9406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9408   arrIo->alloc((int)(sz+1),1);
9409   const int *idsIt=idsOfSelectBg;
9410   int *work=arrIo->getPointer();
9411   *work++=0;
9412   int lgth=0;
9413   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9414     {
9415       if(*idsIt>=0 && *idsIt<nbOfGrps)
9416         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9417       else
9418         {
9419           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9420           throw INTERP_KERNEL::Exception(oss.str().c_str());
9421         }
9422       if(lgth>=work[-1])
9423         *work=lgth;
9424       else
9425         {
9426           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9427           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9428           throw INTERP_KERNEL::Exception(oss.str().c_str());
9429         }
9430     }
9431   arro->alloc(lgth,1);
9432   work=arro->getPointer();
9433   idsIt=idsOfSelectBg;
9434   for(std::size_t i=0;i<sz;i++,idsIt++)
9435     {
9436       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9437         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9438       else
9439         {
9440           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9441           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9442           throw INTERP_KERNEL::Exception(oss.str().c_str());
9443         }
9444     }
9445   arrOut=arro.retn();
9446   arrIndexOut=arrIo.retn();
9447 }
9448
9449 /*!
9450  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9451  * 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 ).
9452  * The selection of extraction is done standardly in new2old format.
9453  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9454  *
9455  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9456  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9457  * \param [in] arrIn arr origin array from which the extraction will be done.
9458  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9459  * \param [out] arrOut the resulting array
9460  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9461  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9462  */
9463 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9464                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9465 {
9466   if(!arrIn || !arrIndxIn)
9467     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9468   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9469   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9470     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9471   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9472   const int *arrInPtr=arrIn->getConstPointer();
9473   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9474   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9475   if(nbOfGrps<0)
9476     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9477   int maxSizeOfArr=arrIn->getNumberOfTuples();
9478   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9479   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9480   arrIo->alloc((int)(sz+1),1);
9481   int idsIt=idsOfSelectStart;
9482   int *work=arrIo->getPointer();
9483   *work++=0;
9484   int lgth=0;
9485   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9486     {
9487       if(idsIt>=0 && idsIt<nbOfGrps)
9488         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9489       else
9490         {
9491           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9492           throw INTERP_KERNEL::Exception(oss.str().c_str());
9493         }
9494       if(lgth>=work[-1])
9495         *work=lgth;
9496       else
9497         {
9498           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9499           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9500           throw INTERP_KERNEL::Exception(oss.str().c_str());
9501         }
9502     }
9503   arro->alloc(lgth,1);
9504   work=arro->getPointer();
9505   idsIt=idsOfSelectStart;
9506   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9507     {
9508       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9509         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9510       else
9511         {
9512           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9513           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9514           throw INTERP_KERNEL::Exception(oss.str().c_str());
9515         }
9516     }
9517   arrOut=arro.retn();
9518   arrIndexOut=arrIo.retn();
9519 }
9520
9521 /*!
9522  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9523  * 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
9524  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9525  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9526  *
9527  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9528  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9529  * \param [in] arrIn arr origin array from which the extraction will be done.
9530  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9531  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9532  * \param [in] srcArrIndex index array of \b srcArr
9533  * \param [out] arrOut the resulting array
9534  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9535  * 
9536  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9537  */
9538 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9539                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9540                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9541 {
9542   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9543     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9544   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9545   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9546   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9547   std::vector<bool> v(nbOfTuples,true);
9548   int offset=0;
9549   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9550   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9551   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9552     {
9553       if(*it>=0 && *it<nbOfTuples)
9554         {
9555           v[*it]=false;
9556           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9557         }
9558       else
9559         {
9560           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9561           throw INTERP_KERNEL::Exception(oss.str().c_str());
9562         }
9563     }
9564   srcArrIndexPtr=srcArrIndex->getConstPointer();
9565   arrIo->alloc(nbOfTuples+1,1);
9566   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9567   const int *arrInPtr=arrIn->getConstPointer();
9568   const int *srcArrPtr=srcArr->getConstPointer();
9569   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9570   int *arroPtr=arro->getPointer();
9571   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9572     {
9573       if(v[ii])
9574         {
9575           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9576           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9577         }
9578       else
9579         {
9580           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9581           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9582           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9583         }
9584     }
9585   arrOut=arro.retn();
9586   arrIndexOut=arrIo.retn();
9587 }
9588
9589 /*!
9590  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9591  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9592  *
9593  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9594  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9595  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9596  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9597  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9598  * \param [in] srcArrIndex index array of \b srcArr
9599  * 
9600  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9601  */
9602 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9603                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9604 {
9605   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9606     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9607   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9608   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9609   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9610   int *arrInOutPtr=arrInOut->getPointer();
9611   const int *srcArrPtr=srcArr->getConstPointer();
9612   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9613     {
9614       if(*it>=0 && *it<nbOfTuples)
9615         {
9616           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9617             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9618           else
9619             {
9620               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] !";
9621               throw INTERP_KERNEL::Exception(oss.str().c_str());
9622             }
9623         }
9624       else
9625         {
9626           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9627           throw INTERP_KERNEL::Exception(oss.str().c_str());
9628         }
9629     }
9630 }
9631
9632 /*!
9633  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9634  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9635  * 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]].
9636  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9637  * A negative value in \b arrIn means that it is ignored.
9638  * 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.
9639  * 
9640  * \param [in] arrIn arr origin array from which the extraction will be done.
9641  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9642  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9643  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9644  */
9645 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9646 {
9647   int seed=0,nbOfDepthPeelingPerformed=0;
9648   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9649 }
9650
9651 /*!
9652  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9653  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9654  * 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]].
9655  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9656  * A negative value in \b arrIn means that it is ignored.
9657  * 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.
9658  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9659  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9660  * \param [in] arrIn arr origin array from which the extraction will be done.
9661  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9662  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9663  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9664  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9665  * \sa MEDCouplingUMesh::partitionBySpreadZone
9666  */
9667 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9668 {
9669   nbOfDepthPeelingPerformed=0;
9670   if(!arrIndxIn)
9671     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9672   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9673   if(nbOfTuples<=0)
9674     {
9675       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9676       return ret;
9677     }
9678   //
9679   std::vector<bool> fetched(nbOfTuples,false);
9680   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9681 }
9682
9683 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9684 {
9685   nbOfDepthPeelingPerformed=0;
9686   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9687     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9688   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9689   std::vector<bool> fetched2(nbOfTuples,false);
9690   int i=0;
9691   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9692     {
9693       if(*seedElt>=0 && *seedElt<nbOfTuples)
9694         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9695       else
9696         { 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()); }
9697     }
9698   const int *arrInPtr=arrIn->getConstPointer();
9699   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9700   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9701   std::vector<int> idsToFetch1(seedBg,seedEnd);
9702   std::vector<int> idsToFetch2;
9703   std::vector<int> *idsToFetch=&idsToFetch1;
9704   std::vector<int> *idsToFetchOther=&idsToFetch2;
9705   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9706     {
9707       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9708         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9709           if(!fetched[*it2])
9710             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9711       std::swap(idsToFetch,idsToFetchOther);
9712       idsToFetchOther->clear();
9713       nbOfDepthPeelingPerformed++;
9714     }
9715   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9716   i=0;
9717   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9718   int *retPtr=ret->getPointer();
9719   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9720     if(*it)
9721       *retPtr++=i;
9722   return ret.retn();
9723 }
9724
9725 /*!
9726  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9727  * 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
9728  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9729  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9730  *
9731  * \param [in] start begin of set of ids of the input extraction (included)
9732  * \param [in] end end of set of ids of the input extraction (excluded)
9733  * \param [in] step step of the set of ids in range mode.
9734  * \param [in] arrIn arr origin array from which the extraction will be done.
9735  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9736  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9737  * \param [in] srcArrIndex index array of \b srcArr
9738  * \param [out] arrOut the resulting array
9739  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9740  * 
9741  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9742  */
9743 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9744                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9745                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9746 {
9747   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9749   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9750   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9751   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9752   int offset=0;
9753   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9754   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9755   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9756   int it=start;
9757   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9758     {
9759       if(it>=0 && it<nbOfTuples)
9760         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9761       else
9762         {
9763           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9764           throw INTERP_KERNEL::Exception(oss.str().c_str());
9765         }
9766     }
9767   srcArrIndexPtr=srcArrIndex->getConstPointer();
9768   arrIo->alloc(nbOfTuples+1,1);
9769   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9770   const int *arrInPtr=arrIn->getConstPointer();
9771   const int *srcArrPtr=srcArr->getConstPointer();
9772   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9773   int *arroPtr=arro->getPointer();
9774   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9775     {
9776       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9777       if(pos<0)
9778         {
9779           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9780           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9781         }
9782       else
9783         {
9784           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9785           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9786         }
9787     }
9788   arrOut=arro.retn();
9789   arrIndexOut=arrIo.retn();
9790 }
9791
9792 /*!
9793  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9794  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9795  *
9796  * \param [in] start begin of set of ids of the input extraction (included)
9797  * \param [in] end end of set of ids of the input extraction (excluded)
9798  * \param [in] step step of the set of ids in range mode.
9799  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9800  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9801  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9802  * \param [in] srcArrIndex index array of \b srcArr
9803  * 
9804  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9805  */
9806 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9807                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9808 {
9809   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9811   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9812   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9813   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9814   int *arrInOutPtr=arrInOut->getPointer();
9815   const int *srcArrPtr=srcArr->getConstPointer();
9816   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9817   int it=start;
9818   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9819     {
9820       if(it>=0 && it<nbOfTuples)
9821         {
9822           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9823             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9824           else
9825             {
9826               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9827               throw INTERP_KERNEL::Exception(oss.str().c_str());
9828             }
9829         }
9830       else
9831         {
9832           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9833           throw INTERP_KERNEL::Exception(oss.str().c_str());
9834         }
9835     }
9836 }
9837
9838 /*!
9839  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9840  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9841  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9842  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9843  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9844  * 
9845  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9846  */
9847 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9848 {
9849   checkFullyDefined();
9850   int mdim=getMeshDimension();
9851   int spaceDim=getSpaceDimension();
9852   if(mdim!=spaceDim)
9853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9854   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9855   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9856   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9857   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9858   ret->setCoords(getCoords());
9859   ret->allocateCells((int)partition.size());
9860   //
9861   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9862     {
9863       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9864       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9865       switch(mdim)
9866         {
9867         case 2:
9868           cell=tmp->buildUnionOf2DMesh();
9869           break;
9870         case 3:
9871           cell=tmp->buildUnionOf3DMesh();
9872           break;
9873         default:
9874           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9875         }
9876       
9877       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9878     }
9879   //
9880   ret->finishInsertingCells();
9881   return ret.retn();
9882 }
9883
9884 /*!
9885  * This method partitions \b this into contiguous zone.
9886  * This method only needs a well defined connectivity. Coordinates are not considered here.
9887  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9888  */
9889 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9890 {
9891   int nbOfCellsCur=getNumberOfCells();
9892   std::vector<DataArrayInt *> ret;
9893   if(nbOfCellsCur<=0)
9894     return ret;
9895   DataArrayInt *neigh=0,*neighI=0;
9896   computeNeighborsOfCells(neigh,neighI);
9897   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9898   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9899   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9900   int seed=0;
9901   while(seed<nbOfCellsCur)
9902     {
9903       int nbOfPeelPerformed=0;
9904       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9905       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9906     }
9907   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9908     ret.push_back((*it).retn());
9909   return ret;
9910 }
9911
9912 /*!
9913  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9914  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9915  *
9916  * \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.
9917  * \return a newly allocated DataArrayInt to be managed by the caller.
9918  * \throw In case of \a code has not the right format (typically of size 3*n)
9919  */
9920 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9921 {
9922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9923   std::size_t nb=code.size()/3;
9924   if(code.size()%3!=0)
9925     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9926   ret->alloc((int)nb,2);
9927   int *retPtr=ret->getPointer();
9928   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9929     {
9930       retPtr[0]=code[3*i+2];
9931       retPtr[1]=code[3*i+2]+code[3*i+1];
9932     }
9933   return ret.retn();
9934 }
9935
9936 /*!
9937  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9938  * All cells in \a this are expected to be linear 3D cells.
9939  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9940  * It leads to an increase to number of cells.
9941  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9942  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
9943  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9944  *
9945  * \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.
9946  *                      For all other cells, the splitting policy will be ignored.
9947  * \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. 
9948  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9949  *          an id of old cell producing it. The caller is to delete this array using
9950  *         decrRef() as it is no more needed.
9951  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9952  *
9953  * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
9954  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
9955  * 
9956  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9957  * \throw If \a this is not fully constituted with linear 3D cells.
9958  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
9959  */
9960 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
9961 {
9962   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9963   checkConnectivityFullyDefined();
9964   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9966   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9967   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
9968   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9969   int *retPt(ret->getPointer());
9970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9971   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9972   const int *oldc(_nodal_connec->begin());
9973   const int *oldci(_nodal_connec_index->begin());
9974   const double *coords(_coords->begin());
9975   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9976     {
9977       std::vector<int> a; std::vector<double> b;
9978       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9979       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9980       const int *aa(&a[0]);
9981       if(!b.empty())
9982         {
9983           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9984             if(*it<0)
9985               *it=(-(*(it))-1+nbNodes);
9986           addPts->insertAtTheEnd(b.begin(),b.end());
9987           nbNodes+=(int)b.size()/3;
9988         }
9989       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9990         newConn->insertAtTheEnd(aa,aa+4);
9991     }
9992   if(!addPts->empty())
9993     {
9994       addPts->rearrange(3);
9995       nbOfAdditionalPoints=addPts->getNumberOfTuples();
9996       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9997       ret0->setCoords(addPts);
9998     }
9999   else
10000     {
10001       nbOfAdditionalPoints=0;
10002       ret0->setCoords(getCoords());
10003     }
10004   ret0->setNodalConnectivity(newConn);
10005   //
10006   ret->computeOffsets2();
10007   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
10008   return ret0.retn();
10009 }
10010
10011 /*!
10012  * It is the linear part of MEDCouplingUMesh::split2DCells. Here no additionnal nodes will be added in \b this. So coordinates pointer remain unchanged (is not even touch). 
10013  *
10014  * \sa MEDCouplingUMesh::split2DCells
10015  */
10016 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
10017 {
10018   checkConnectivityFullyDefined();
10019   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
10020   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10021   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10022   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10023   int prevPosOfCi(ciPtr[0]);
10024   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10025     {
10026       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
10027       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
10028       for(int j=0;j<sz;j++)
10029         {
10030           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
10031           for(int k=0;k<sz2;k++)
10032             *cPtr++=subPtr[offset2+k];
10033           if(j!=sz-1)
10034             *cPtr++=oldConn[prevPosOfCi+j+2];
10035           deltaSz+=sz2;
10036         }
10037       prevPosOfCi=ciPtr[1];
10038       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10039     }
10040   if(c->end()!=cPtr)
10041     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
10042   _nodal_connec->decrRef();
10043   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
10044 }
10045
10046 int internalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
10047 {
10048   if(id!=-1)
10049     return id;
10050   else
10051     {
10052       int ret(nodesCnter++);
10053       double newPt[2];
10054       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
10055       addCoo.insertAtTheEnd(newPt,newPt+2);
10056       return ret;
10057     }
10058 }
10059
10060 /*!
10061  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
10062  *
10063  * \return  int - the number of new nodes created.
10064  * \sa MEDCouplingUMesh::split2DCells
10065  */
10066 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
10067 {
10068   checkCoherency();
10069   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
10070   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10071   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
10072   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10073   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
10074   const double *oldCoordsPtr(getCoords()->begin());
10075   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10076   int prevPosOfCi(ciPtr[0]);
10077   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10078     {
10079       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
10080       for(int j=0;j<sz;j++)
10081         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
10082       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
10083       for(int j=0;j<sz;j++)//loop over subedges of oldConn
10084         {
10085           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
10086           if(sz2==0)
10087             {
10088               if(j<sz-1)
10089                 cPtr[1]=oldConn[prevPosOfCi+2+j];
10090               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
10091               continue;
10092             }
10093           std::vector<INTERP_KERNEL::Node *> ns(3);
10094           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
10095           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
10096           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
10097           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
10098           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
10099             {
10100               cPtr[1]=subPtr[offset2+k];
10101               cPtr[deltaSz]=internalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
10102             }
10103           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
10104           if(j!=sz-1)
10105             { cPtr[1]=tmpEnd; }
10106           cPtr[deltaSz]=internalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
10107         }
10108       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
10109       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10110     }
10111   if(c->end()!=cPtr)
10112     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
10113   _nodal_connec->decrRef();
10114   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
10115   addCoo->rearrange(2);
10116   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
10117   setCoords(coo);
10118   return addCoo->getNumberOfTuples();
10119 }
10120
10121 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
10122                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
10123 {
10124   if(mesh)
10125     {
10126       mesh->incrRef();
10127       _nb_cell=mesh->getNumberOfCells();
10128     }
10129 }
10130
10131 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
10132 {
10133   if(_mesh)
10134     _mesh->decrRef();
10135   if(_own_cell)
10136     delete _cell;
10137 }
10138
10139 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
10140                                                                                                                                _own_cell(false),_cell_id(bg-1),
10141                                                                                                                                _nb_cell(end)
10142 {
10143   if(mesh)
10144     mesh->incrRef();
10145 }
10146
10147 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
10148 {
10149   _cell_id++;
10150   if(_cell_id<_nb_cell)
10151     {
10152       _cell->next();
10153       return _cell;
10154     }
10155   else
10156     return 0;
10157 }
10158
10159 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
10160 {
10161   if(_mesh)
10162     _mesh->incrRef();
10163 }
10164
10165 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
10166 {
10167   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
10168 }
10169
10170 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
10171 {
10172   if(_mesh)
10173     _mesh->decrRef();
10174 }
10175
10176 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
10177                                                                                                                                                                   _itc(itc),
10178                                                                                                                                                                   _bg(bg),_end(end)
10179 {
10180   if(_mesh)
10181     _mesh->incrRef();
10182 }
10183
10184 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
10185 {
10186   if(_mesh)
10187     _mesh->decrRef();
10188 }
10189
10190 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
10191 {
10192   return _type;
10193 }
10194
10195 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
10196 {
10197   return _end-_bg;
10198 }
10199
10200 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
10201 {
10202   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
10203 }
10204
10205 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
10206 {
10207   if(mesh)
10208     {
10209       mesh->incrRef();
10210       _nb_cell=mesh->getNumberOfCells();
10211     }
10212 }
10213
10214 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
10215 {
10216   if(_mesh)
10217     _mesh->decrRef();
10218   delete _cell;
10219 }
10220
10221 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
10222 {
10223   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
10224   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
10225   if(_cell_id<_nb_cell)
10226     {
10227       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
10228       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
10229       int startId=_cell_id;
10230       _cell_id+=nbOfElems;
10231       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
10232     }
10233   else
10234     return 0;
10235 }
10236
10237 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
10238 {
10239   if(mesh)
10240     {
10241       _conn=mesh->getNodalConnectivity()->getPointer();
10242       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
10243     }
10244 }
10245
10246 void MEDCouplingUMeshCell::next()
10247 {
10248   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10249     {
10250       _conn+=_conn_lgth;
10251       _conn_indx++;
10252     }
10253   _conn_lgth=_conn_indx[1]-_conn_indx[0];
10254 }
10255
10256 std::string MEDCouplingUMeshCell::repr() const
10257 {
10258   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10259     {
10260       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
10261       oss << " : ";
10262       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
10263       return oss.str();
10264     }
10265   else
10266     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
10267 }
10268
10269 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
10270 {
10271   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10272     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
10273   else
10274     return INTERP_KERNEL::NORM_ERROR;
10275 }
10276
10277 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
10278 {
10279   lgth=_conn_lgth;
10280   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10281     return _conn;
10282   else
10283     return 0;
10284 }