Salome HOME
Management of lev -1 even for cell fields on structured meshes
[modules/med.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  *  \if ENABLE_EXAMPLES
318  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
319  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
320  *  \endif
321  */
322 void MEDCouplingUMesh::allocateCells(int nbOfCells)
323 {
324   if(nbOfCells<0)
325     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
326   if(_nodal_connec_index)
327     {
328       _nodal_connec_index->decrRef();
329     }
330   if(_nodal_connec)
331     {
332       _nodal_connec->decrRef();
333     }
334   _nodal_connec_index=DataArrayInt::New();
335   _nodal_connec_index->reserve(nbOfCells+1);
336   _nodal_connec_index->pushBackSilent(0);
337   _nodal_connec=DataArrayInt::New();
338   _nodal_connec->reserve(2*nbOfCells);
339   _types.clear();
340   declareAsNew();
341 }
342
343 /*!
344  * Appends a cell to the connectivity array. For deeper understanding what is
345  * happening see \ref MEDCouplingUMeshNodalConnectivity.
346  *  \param [in] type - type of cell to add.
347  *  \param [in] size - number of nodes constituting this cell.
348  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
349  * 
350  *  \if ENABLE_EXAMPLES
351  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
352  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
353  *  \endif
354  */
355 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
356 {
357   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
358   if(_nodal_connec_index==0)
359     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
360   if((int)cm.getDimension()==_mesh_dim)
361     {
362       if(!cm.isDynamic())
363         if(size!=(int)cm.getNumberOfNodes())
364           {
365             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
366             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
367             throw INTERP_KERNEL::Exception(oss.str().c_str());
368           }
369       int idx=_nodal_connec_index->back();
370       int val=idx+size+1;
371       _nodal_connec_index->pushBackSilent(val);
372       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
373       _types.insert(type);
374     }
375   else
376     {
377       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
378       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
379       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
380       throw INTERP_KERNEL::Exception(oss.str().c_str());
381     }
382 }
383
384 /*!
385  * Compacts data arrays to release unused memory. This method is to be called after
386  * finishing cell insertion using \a this->insertNextCell().
387  * 
388  *  \if ENABLE_EXAMPLES
389  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
390  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
391  *  \endif
392  */
393 void MEDCouplingUMesh::finishInsertingCells()
394 {
395   _nodal_connec->pack();
396   _nodal_connec_index->pack();
397   _nodal_connec->declareAsNew();
398   _nodal_connec_index->declareAsNew();
399   updateTime();
400 }
401
402 /*!
403  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
404  * Useful for python users.
405  */
406 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
407 {
408   return new MEDCouplingUMeshCellIterator(this);
409 }
410
411 /*!
412  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
413  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
414  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
415  * Useful for python users.
416  */
417 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
418 {
419   if(!checkConsecutiveCellTypes())
420     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
421   return new MEDCouplingUMeshCellByTypeEntry(this);
422 }
423
424 /*!
425  * Returns a set of all cell types available in \a this mesh.
426  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
427  * \warning this method does not throw any exception even if \a this is not defined.
428  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
429  */
430 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
431 {
432   return _types;
433 }
434
435 /*!
436  * This method returns the sorted list of geometric types in \a this.
437  * 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
438  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
439  *
440  * \throw if connectivity in \a this is not correctly defined.
441  *  
442  * \sa MEDCouplingMesh::getAllGeoTypes
443  */
444 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
445 {
446   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
447   checkConnectivityFullyDefined();
448   int nbOfCells(getNumberOfCells());
449   if(nbOfCells==0)
450     return ret;
451   if(getMeshLength()<1)
452     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
453   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
454   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
455   for(int i=1;i<nbOfCells;i++,ci++)
456     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
457       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
458   return ret;
459 }
460
461 /*!
462  * This method is a method that compares \a this and \a other.
463  * This method compares \b all attributes, even names and component names.
464  */
465 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
466 {
467   if(!other)
468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
469   std::ostringstream oss; oss.precision(15);
470   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
471   if(!otherC)
472     {
473       reason="mesh given in input is not castable in MEDCouplingUMesh !";
474       return false;
475     }
476   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
477     return false;
478   if(_mesh_dim!=otherC->_mesh_dim)
479     {
480       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
481       reason=oss.str();
482       return false;
483     }
484   if(_types!=otherC->_types)
485     {
486       oss << "umesh geometric type mismatch :\nThis geometric types are :";
487       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
488         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
489       oss << "\nOther geometric types are :";
490       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
491         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
492       reason=oss.str();
493       return false;
494     }
495   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
496     if(_nodal_connec==0 || otherC->_nodal_connec==0)
497       {
498         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
499         return false;
500       }
501   if(_nodal_connec!=otherC->_nodal_connec)
502     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
503       {
504         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
505         return false;
506       }
507   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
508     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
509       {
510         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
511         return false;
512       }
513   if(_nodal_connec_index!=otherC->_nodal_connec_index)
514     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
515       {
516         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
517         return false;
518       }
519   return true;
520 }
521
522 /*!
523  * Checks if data arrays of this mesh (node coordinates, nodal
524  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
525  * not considered.
526  *  \param [in] other - the mesh to compare with.
527  *  \param [in] prec - precision value used to compare node coordinates.
528  *  \return bool - \a true if the two meshes are same.
529  */
530 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
531 {
532   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
533   if(!otherC)
534     return false;
535   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
536     return false;
537   if(_mesh_dim!=otherC->_mesh_dim)
538     return false;
539   if(_types!=otherC->_types)
540     return false;
541   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
542     if(_nodal_connec==0 || otherC->_nodal_connec==0)
543       return false;
544   if(_nodal_connec!=otherC->_nodal_connec)
545     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
546       return false;
547   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
548     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
549       return false;
550   if(_nodal_connec_index!=otherC->_nodal_connec_index)
551     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
552       return false;
553   return true;
554 }
555
556 /*!
557  * Checks if \a this and \a other meshes are geometrically equivalent with high
558  * probability, else an exception is thrown. The meshes are considered equivalent if
559  * (1) meshes contain the same number of nodes and the same number of elements of the
560  * same types (2) three cells of the two meshes (first, last and middle) are based
561  * on coincident nodes (with a specified precision).
562  *  \param [in] other - the mesh to compare with.
563  *  \param [in] prec - the precision used to compare nodes of the two meshes.
564  *  \throw If the two meshes do not match.
565  */
566 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
567 {
568  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
569  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
570   if(!otherC)
571     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
572 }
573
574 /*!
575  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
576  * cells each node belongs to.
577  * \warning For speed reasons, this method does not check if node ids in the nodal
578  *          connectivity correspond to the size of node coordinates array.
579  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
580  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
581  *        dividing cell ids in \a revNodal into groups each referring to one
582  *        node. Its every element (except the last one) is an index pointing to the
583  *         first id of a group of cells. For example cells sharing the node #1 are 
584  *        described by following range of indices: 
585  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
586  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
587  *        Number of cells sharing the *i*-th node is
588  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
589  * \throw If the coordinates array is not set.
590  * \throw If the nodal connectivity of cells is not defined.
591  * 
592  * \if ENABLE_EXAMPLES
593  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
594  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
595  * \endif
596  */
597 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
598 {
599   checkFullyDefined();
600   int nbOfNodes=getNumberOfNodes();
601   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
602   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
603   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
604   const int *conn=_nodal_connec->getConstPointer();
605   const int *connIndex=_nodal_connec_index->getConstPointer();
606   int nbOfCells=getNumberOfCells();
607   int nbOfEltsInRevNodal=0;
608   for(int eltId=0;eltId<nbOfCells;eltId++)
609     {
610       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
611       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
612       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
613         if(*iter>=0)//for polyhedrons
614           {
615             nbOfEltsInRevNodal++;
616             revNodalIndxPtr[(*iter)+1]++;
617           }
618     }
619   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
620   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
621   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
622   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
623   for(int eltId=0;eltId<nbOfCells;eltId++)
624     {
625       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
626       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
627       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
628         if(*iter>=0)//for polyhedrons
629           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
630     }
631 }
632
633 /// @cond INTERNAL
634
635 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
636 {
637   return id;
638 }
639
640 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
641 {
642   if(!compute)
643     return id+1;
644   else
645     {
646       if(cm.getOrientationStatus(nb,conn1,conn2))
647         return id+1;
648       else
649         return -(id+1);
650     }
651 }
652
653 class MinusOneSonsGenerator
654 {
655 public:
656   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
657   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
658   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
659   static const int DELTA=1;
660 private:
661   const INTERP_KERNEL::CellModel& _cm;
662 };
663
664 class MinusOneSonsGeneratorBiQuadratic
665 {
666 public:
667   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
668   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
669   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
670   static const int DELTA=1;
671 private:
672   const INTERP_KERNEL::CellModel& _cm;
673 };
674
675 class MinusTwoSonsGenerator
676 {
677 public:
678   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
679   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
680   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
681   static const int DELTA=2;
682 private:
683   const INTERP_KERNEL::CellModel& _cm;
684 };
685
686 /// @endcond
687
688 /*!
689  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
690  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
691  * describing correspondence between cells of \a this and the result meshes are
692  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
693  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
694  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
695  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
696  * \warning For speed reasons, this method does not check if node ids in the nodal
697  *          connectivity correspond to the size of node coordinates array.
698  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
699  *          to write this mesh to the MED file, its cells must be sorted using
700  *          sortCellsInMEDFileFrmt().
701  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
702  *         each cell of \a this mesh.
703  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
704  *        dividing cell ids in \a desc into groups each referring to one
705  *        cell of \a this mesh. Its every element (except the last one) is an index
706  *        pointing to the first id of a group of cells. For example cells of the
707  *        result mesh bounding the cell #1 of \a this mesh are described by following
708  *        range of indices:
709  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
710  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
711  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
712  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
713  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
714  *         by each cell of the result mesh.
715  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
716  *        in the result mesh,
717  *        dividing cell ids in \a revDesc into groups each referring to one
718  *        cell of the result mesh the same way as \a descIndx divides \a desc.
719  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
720  *        delete this mesh using decrRef() as it is no more needed.
721  *  \throw If the coordinates array is not set.
722  *  \throw If the nodal connectivity of cells is node defined.
723  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
724  *         revDescIndx == NULL.
725  * 
726  *  \if ENABLE_EXAMPLES
727  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
728  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
729  *  \endif
730  * \sa buildDescendingConnectivity2()
731  */
732 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
733 {
734   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
735 }
736
737 /*!
738  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
739  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
740  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
741  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
742  * \sa MEDCouplingUMesh::buildDescendingConnectivity
743  */
744 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
745 {
746   checkFullyDefined();
747   if(getMeshDimension()!=3)
748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
749   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
750 }
751
752 /*!
753  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
754  * this->getMeshDimension(), that bound cells of \a this mesh. In
755  * addition arrays describing correspondence between cells of \a this and the result
756  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
757  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
758  *  mesh. This method differs from buildDescendingConnectivity() in that apart
759  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
760  * result meshes. So a positive id means that order of nodes in corresponding cells
761  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
762  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
763  * i.e. cell ids are one-based.
764  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
765  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
766  * \warning For speed reasons, this method does not check if node ids in the nodal
767  *          connectivity correspond to the size of node coordinates array.
768  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
769  *          to write this mesh to the MED file, its cells must be sorted using
770  *          sortCellsInMEDFileFrmt().
771  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
772  *         each cell of \a this mesh.
773  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
774  *        dividing cell ids in \a desc into groups each referring to one
775  *        cell of \a this mesh. Its every element (except the last one) is an index
776  *        pointing to the first id of a group of cells. For example cells of the
777  *        result mesh bounding the cell #1 of \a this mesh are described by following
778  *        range of indices:
779  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
780  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
781  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
782  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
783  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
784  *         by each cell of the result mesh.
785  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
786  *        in the result mesh,
787  *        dividing cell ids in \a revDesc into groups each referring to one
788  *        cell of the result mesh the same way as \a descIndx divides \a desc.
789  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
790  *        shares the node coordinates array with \a this mesh. The caller is to
791  *        delete this mesh using decrRef() as it is no more needed.
792  *  \throw If the coordinates array is not set.
793  *  \throw If the nodal connectivity of cells is node defined.
794  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
795  *         revDescIndx == NULL.
796  * 
797  *  \if ENABLE_EXAMPLES
798  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
799  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
800  *  \endif
801  * \sa buildDescendingConnectivity()
802  */
803 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
804 {
805   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
806 }
807
808 /*!
809  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
810  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
811  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
812  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
813  *
814  * \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
815  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
816  * \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.
817  */
818 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
819 {
820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
823   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
824   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
825   meshDM1=0;
826   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
827 }
828
829 /*!
830  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
831  * 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,
832  * excluding a set of meshdim-1 cells in input descending connectivity.
833  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
834  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
835  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
836  *
837  * \param [in] desc descending connectivity array.
838  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
839  * \param [in] revDesc reverse descending connectivity array.
840  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
841  * \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
842  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
843  * \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.
844  */
845 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
846                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
847 {
848   if(!desc || !descIndx || !revDesc || !revDescIndx)
849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
850   const int *descPtr=desc->getConstPointer();
851   const int *descIPtr=descIndx->getConstPointer();
852   const int *revDescPtr=revDesc->getConstPointer();
853   const int *revDescIPtr=revDescIndx->getConstPointer();
854   //
855   int nbCells=descIndx->getNumberOfTuples()-1;
856   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
858   int *out1Ptr=out1->getPointer();
859   *out1Ptr++=0;
860   out0->reserve(desc->getNumberOfTuples());
861   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
862     {
863       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
864         {
865           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
866           s.erase(i);
867           out0->insertAtTheEnd(s.begin(),s.end());
868         }
869       *out1Ptr=out0->getNumberOfTuples();
870     }
871   neighbors=out0.retn();
872   neighborsIndx=out1.retn();
873 }
874
875 /// @cond INTERNAL
876
877 /*!
878  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
879  * For speed reasons no check of this will be done.
880  */
881 template<class SonsGenerator>
882 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
883 {
884   if(!desc || !descIndx || !revDesc || !revDescIndx)
885     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
886   checkConnectivityFullyDefined();
887   int nbOfCells=getNumberOfCells();
888   int nbOfNodes=getNumberOfNodes();
889   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
890   int *revNodalIndxPtr=revNodalIndx->getPointer();
891   const int *conn=_nodal_connec->getConstPointer();
892   const int *connIndex=_nodal_connec_index->getConstPointer();
893   std::string name="Mesh constituent of "; name+=getName();
894   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
895   ret->setCoords(getCoords());
896   ret->allocateCells(2*nbOfCells);
897   descIndx->alloc(nbOfCells+1,1);
898   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
899   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
900   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
901     {
902       int pos=connIndex[eltId];
903       int posP1=connIndex[eltId+1];
904       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
905       SonsGenerator sg(cm);
906       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
907       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
908       for(unsigned i=0;i<nbOfSons;i++)
909         {
910           INTERP_KERNEL::NormalizedCellType cmsId;
911           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
912           for(unsigned k=0;k<nbOfNodesSon;k++)
913             if(tmp[k]>=0)
914               revNodalIndxPtr[tmp[k]+1]++;
915           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
916           revDesc2->pushBackSilent(eltId);
917         }
918       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
919     }
920   int nbOfCellsM1=ret->getNumberOfCells();
921   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
923   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
924   int *revNodalPtr=revNodal->getPointer();
925   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
926   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
927   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
928     {
929       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
930       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
931       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
932         if(*iter>=0)//for polyhedrons
933           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
934     }
935   //
936   DataArrayInt *commonCells=0,*commonCellsI=0;
937   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
938   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
939   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
940   int newNbOfCellsM1=-1;
941   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
942                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
943   std::vector<bool> isImpacted(nbOfCellsM1,false);
944   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
945     for(int work2=work[0];work2!=work[1];work2++)
946       isImpacted[commonCellsPtr[work2]]=true;
947   const int *o2nM1Ptr=o2nM1->getConstPointer();
948   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
949   const int *n2oM1Ptr=n2oM1->getConstPointer();
950   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
951   ret2->copyTinyInfoFrom(this);
952   desc->alloc(descIndx->back(),1);
953   int *descPtr=desc->getPointer();
954   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
955   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
956     {
957       if(!isImpacted[i])
958         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
959       else
960         {
961           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
962             {
963               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
964               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
965             }
966           else
967             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
968         }
969     }
970   revDesc->reserve(newNbOfCellsM1);
971   revDescIndx->alloc(newNbOfCellsM1+1,1);
972   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
973   const int *revDesc2Ptr=revDesc2->getConstPointer();
974   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
975     {
976       int oldCellIdM1=n2oM1Ptr[i];
977       if(!isImpacted[oldCellIdM1])
978         {
979           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
980           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
981         }
982       else
983         {
984           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
985             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
986           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
987           commonCellsIPtr++;
988         }
989     }
990   //
991   return ret2.retn();
992 }
993
994 struct MEDCouplingAccVisit
995 {
996   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
997   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
998   int _new_nb_of_nodes;
999 };
1000
1001 /// @endcond
1002
1003 /*!
1004  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1005  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1006  * array of cell ids. Pay attention that after conversion all algorithms work slower
1007  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1008  * conversion due presence of invalid ids in the array of cells to convert, as a
1009  * result \a this mesh contains some already converted elements. In this case the 2D
1010  * mesh remains valid but 3D mesh becomes \b inconsistent!
1011  *  \warning This method can significantly modify the order of geometric types in \a this,
1012  *          hence, to write this mesh to the MED file, its cells must be sorted using
1013  *          sortCellsInMEDFileFrmt().
1014  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1015  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1016  *         cellIdsToConvertBg.
1017  *  \throw If the coordinates array is not set.
1018  *  \throw If the nodal connectivity of cells is node defined.
1019  *  \throw If dimension of \a this mesh is not either 2 or 3.
1020  *
1021  *  \if ENABLE_EXAMPLES
1022  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1023  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1024  *  \endif
1025  */
1026 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1027 {
1028   checkFullyDefined();
1029   int dim=getMeshDimension();
1030   if(dim<2 || dim>3)
1031     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1032   int nbOfCells(getNumberOfCells());
1033   if(dim==2)
1034     {
1035       const int *connIndex=_nodal_connec_index->getConstPointer();
1036       int *conn=_nodal_connec->getPointer();
1037       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1038         {
1039           if(*iter>=0 && *iter<nbOfCells)
1040             {
1041               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1042               if(!cm.isQuadratic())
1043                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1044               else
1045                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1046             }
1047           else
1048             {
1049               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1050               oss << " in range [0," << nbOfCells << ") !";
1051               throw INTERP_KERNEL::Exception(oss.str().c_str());
1052             }
1053         }
1054     }
1055   else
1056     {
1057       int *connIndex(_nodal_connec_index->getPointer());
1058       const int *connOld(_nodal_connec->getConstPointer());
1059       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1060       std::vector<bool> toBeDone(nbOfCells,false);
1061       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1062         {
1063           if(*iter>=0 && *iter<nbOfCells)
1064             toBeDone[*iter]=true;
1065           else
1066             {
1067               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1068               oss << " in range [0," << nbOfCells << ") !";
1069               throw INTERP_KERNEL::Exception(oss.str().c_str());
1070             }
1071         }
1072       for(int cellId=0;cellId<nbOfCells;cellId++)
1073         {
1074           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1075           int lgthOld(posP1-pos-1);
1076           if(toBeDone[cellId])
1077             {
1078               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1079               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1080               int *tmp(new int[nbOfFaces*lgthOld+1]);
1081               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1082               for(unsigned j=0;j<nbOfFaces;j++)
1083                 {
1084                   INTERP_KERNEL::NormalizedCellType type;
1085                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1086                   work+=offset;
1087                   *work++=-1;
1088                 }
1089               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1090               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1091               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1092               delete [] tmp;
1093             }
1094           else
1095             {
1096               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1097               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1098             }
1099         }
1100       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1101     }
1102   computeTypes();
1103 }
1104
1105 /*!
1106  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1107  * polyhedrons (if \a this is a 3D mesh).
1108  *  \warning As this method is purely for user-friendliness and no optimization is
1109  *          done to avoid construction of a useless vector, this method can be costly
1110  *          in memory.
1111  *  \throw If the coordinates array is not set.
1112  *  \throw If the nodal connectivity of cells is node defined.
1113  *  \throw If dimension of \a this mesh is not either 2 or 3.
1114  */
1115 void MEDCouplingUMesh::convertAllToPoly()
1116 {
1117   int nbOfCells=getNumberOfCells();
1118   std::vector<int> cellIds(nbOfCells);
1119   for(int i=0;i<nbOfCells;i++)
1120     cellIds[i]=i;
1121   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1122 }
1123
1124 /*!
1125  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1126  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1127  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1128  * base facet of the volume and the second half of nodes describes an opposite facet
1129  * having the same number of nodes as the base one. This method converts such
1130  * connectivity to a valid polyhedral format where connectivity of each facet is
1131  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1132  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1133  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1134  * a correct orientation of the first facet of a polyhedron, else orientation of a
1135  * corrected cell is reverse.<br>
1136  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1137  * it releases the user from boring description of polyhedra connectivity in the valid
1138  * format.
1139  *  \throw If \a this->getMeshDimension() != 3.
1140  *  \throw If \a this->getSpaceDimension() != 3.
1141  *  \throw If the nodal connectivity of cells is not defined.
1142  *  \throw If the coordinates array is not set.
1143  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1144  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1145  *
1146  *  \if ENABLE_EXAMPLES
1147  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1148  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1149  *  \endif
1150  */
1151 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1152 {
1153   checkFullyDefined();
1154   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1155     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1156   int nbOfCells=getNumberOfCells();
1157   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1158   newCi->alloc(nbOfCells+1,1);
1159   int *newci=newCi->getPointer();
1160   const int *ci=_nodal_connec_index->getConstPointer();
1161   const int *c=_nodal_connec->getConstPointer();
1162   newci[0]=0;
1163   for(int i=0;i<nbOfCells;i++)
1164     {
1165       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1166       if(type==INTERP_KERNEL::NORM_POLYHED)
1167         {
1168           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1169             {
1170               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1171               throw INTERP_KERNEL::Exception(oss.str().c_str());
1172             }
1173           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1174           if(n2%2!=0)
1175             {
1176               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 !";
1177               throw INTERP_KERNEL::Exception(oss.str().c_str());
1178             }
1179           int n1=(int)(n2/2);
1180           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)
1181         }
1182       else
1183         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1184     }
1185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1186   newC->alloc(newci[nbOfCells],1);
1187   int *newc=newC->getPointer();
1188   for(int i=0;i<nbOfCells;i++)
1189     {
1190       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1191       if(type==INTERP_KERNEL::NORM_POLYHED)
1192         {
1193           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1194           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1195           *newc++=-1;
1196           for(std::size_t j=0;j<n1;j++)
1197             {
1198               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1199               newc[n1+5*j]=-1;
1200               newc[n1+5*j+1]=c[ci[i]+1+j];
1201               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1202               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1203               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1204             }
1205           newc+=n1*6;
1206         }
1207       else
1208         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1209     }
1210   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1211   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1212 }
1213
1214
1215 /*!
1216  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1217  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1218  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1219  *          to write this mesh to the MED file, its cells must be sorted using
1220  *          sortCellsInMEDFileFrmt().
1221  * \return \c true if at least one cell has been converted, \c false else. In the
1222  *         last case the nodal connectivity remains unchanged.
1223  * \throw If the coordinates array is not set.
1224  * \throw If the nodal connectivity of cells is not defined.
1225  * \throw If \a this->getMeshDimension() < 0.
1226  */
1227 bool MEDCouplingUMesh::unPolyze()
1228 {
1229   checkFullyDefined();
1230   int mdim=getMeshDimension();
1231   if(mdim<0)
1232     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1233   if(mdim<=1)
1234     return false;
1235   int nbOfCells=getNumberOfCells();
1236   if(nbOfCells<1)
1237     return false;
1238   int initMeshLgth=getMeshLength();
1239   int *conn=_nodal_connec->getPointer();
1240   int *index=_nodal_connec_index->getPointer();
1241   int posOfCurCell=0;
1242   int newPos=0;
1243   int lgthOfCurCell;
1244   bool ret=false;
1245   for(int i=0;i<nbOfCells;i++)
1246     {
1247       lgthOfCurCell=index[i+1]-posOfCurCell;
1248       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1249       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1250       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1251       int newLgth;
1252       if(cm.isDynamic())
1253         {
1254           switch(cm.getDimension())
1255             {
1256             case 2:
1257               {
1258                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1259                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1260                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1261                 break;
1262               }
1263             case 3:
1264               {
1265                 int nbOfFaces,lgthOfPolyhConn;
1266                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1267                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1268                 break;
1269               }
1270             case 1:
1271               {
1272                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1273                 break;
1274               }
1275             }
1276           ret=ret || (newType!=type);
1277           conn[newPos]=newType;
1278           newPos+=newLgth+1;
1279           posOfCurCell=index[i+1];
1280           index[i+1]=newPos;
1281         }
1282       else
1283         {
1284           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1285           newPos+=lgthOfCurCell;
1286           posOfCurCell+=lgthOfCurCell;
1287           index[i+1]=newPos;
1288         }
1289     }
1290   if(newPos!=initMeshLgth)
1291     _nodal_connec->reAlloc(newPos);
1292   if(ret)
1293     computeTypes();
1294   return ret;
1295 }
1296
1297 /*!
1298  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1299  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1300  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1301  *
1302  * \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 
1303  *             precision.
1304  */
1305 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1306 {
1307   checkFullyDefined();
1308   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1309     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1310   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1311   coords->recenterForMaxPrecision(eps);
1312   //
1313   int nbOfCells=getNumberOfCells();
1314   const int *conn=_nodal_connec->getConstPointer();
1315   const int *index=_nodal_connec_index->getConstPointer();
1316   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1317   connINew->alloc(nbOfCells+1,1);
1318   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1320   bool changed=false;
1321   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1322     {
1323       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1324         {
1325           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1326           changed=true;
1327         }
1328       else
1329         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1330       *connINewPtr=connNew->getNumberOfTuples();
1331     }
1332   if(changed)
1333     setConnectivity(connNew,connINew,false);
1334 }
1335
1336 /*!
1337  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1338  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1339  * the format of returned DataArrayInt instance.
1340  * 
1341  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1342  * \sa MEDCouplingUMesh::getNodeIdsInUse
1343  */
1344 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1345 {
1346   checkConnectivityFullyDefined();
1347   int nbOfCells=getNumberOfCells();
1348   const int *connIndex=_nodal_connec_index->getConstPointer();
1349   const int *conn=_nodal_connec->getConstPointer();
1350   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1351   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1352   std::vector<bool> retS(maxElt,false);
1353   for(int i=0;i<nbOfCells;i++)
1354     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1355       if(conn[j]>=0)
1356         retS[conn[j]]=true;
1357   int sz=0;
1358   for(int i=0;i<maxElt;i++)
1359     if(retS[i])
1360       sz++;
1361   DataArrayInt *ret=DataArrayInt::New();
1362   ret->alloc(sz,1);
1363   int *retPtr=ret->getPointer();
1364   for(int i=0;i<maxElt;i++)
1365     if(retS[i])
1366       *retPtr++=i;
1367   return ret;
1368 }
1369
1370 /*!
1371  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1372  * \sa MEDCouplingUMesh::getNodeIdsInUse
1373  */
1374 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1375 {
1376   int nbOfNodes=(int)nodeIdsInUse.size();
1377   int nbOfCells=getNumberOfCells();
1378   const int *connIndex=_nodal_connec_index->getConstPointer();
1379   const int *conn=_nodal_connec->getConstPointer();
1380   for(int i=0;i<nbOfCells;i++)
1381     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1382       if(conn[j]>=0)
1383         {
1384           if(conn[j]<nbOfNodes)
1385             nodeIdsInUse[conn[j]]=true;
1386           else
1387             {
1388               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1389               throw INTERP_KERNEL::Exception(oss.str().c_str());
1390             }
1391         }
1392 }
1393
1394 /*!
1395  * Finds nodes not used in any cell and returns an array giving a new id to every node
1396  * by excluding the unused nodes, for which the array holds -1. The result array is
1397  * a mapping in "Old to New" mode. 
1398  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1399  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1400  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1401  *          if the node is unused or a new id else. The caller is to delete this
1402  *          array using decrRef() as it is no more needed.  
1403  *  \throw If the coordinates array is not set.
1404  *  \throw If the nodal connectivity of cells is not defined.
1405  *  \throw If the nodal connectivity includes an invalid id.
1406  *
1407  *  \if ENABLE_EXAMPLES
1408  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1409  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1410  *  \endif
1411  * \sa computeNodeIdsAlg()
1412  */
1413 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1414 {
1415   nbrOfNodesInUse=-1;
1416   int nbOfNodes=getNumberOfNodes();
1417   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1418   ret->alloc(nbOfNodes,1);
1419   int *traducer=ret->getPointer();
1420   std::fill(traducer,traducer+nbOfNodes,-1);
1421   int nbOfCells=getNumberOfCells();
1422   const int *connIndex=_nodal_connec_index->getConstPointer();
1423   const int *conn=_nodal_connec->getConstPointer();
1424   for(int i=0;i<nbOfCells;i++)
1425     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1426       if(conn[j]>=0)
1427         {
1428           if(conn[j]<nbOfNodes)
1429             traducer[conn[j]]=1;
1430           else
1431             {
1432               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1433               throw INTERP_KERNEL::Exception(oss.str().c_str());
1434             }
1435         }
1436   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1437   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1438   return ret.retn();
1439 }
1440
1441 /*!
1442  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1443  * For each cell in \b this the number of nodes constituting cell is computed.
1444  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1445  * So for pohyhedrons some nodes can be counted several times in the returned result.
1446  * 
1447  * \return a newly allocated array
1448  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1449  */
1450 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1451 {
1452   checkConnectivityFullyDefined();
1453   int nbOfCells=getNumberOfCells();
1454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1455   ret->alloc(nbOfCells,1);
1456   int *retPtr=ret->getPointer();
1457   const int *conn=getNodalConnectivity()->getConstPointer();
1458   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1459   for(int i=0;i<nbOfCells;i++,retPtr++)
1460     {
1461       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1462         *retPtr=connI[i+1]-connI[i]-1;
1463       else
1464         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1465     }
1466   return ret.retn();
1467 }
1468
1469 /*!
1470  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1471  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1472  *
1473  * \return DataArrayInt * - new object to be deallocated by the caller.
1474  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1475  */
1476 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1477 {
1478   checkConnectivityFullyDefined();
1479   int nbOfCells=getNumberOfCells();
1480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1481   ret->alloc(nbOfCells,1);
1482   int *retPtr=ret->getPointer();
1483   const int *conn=getNodalConnectivity()->getConstPointer();
1484   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1485   for(int i=0;i<nbOfCells;i++,retPtr++)
1486     {
1487       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1488       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1489         *retPtr=(int)s.size();
1490       else
1491         {
1492           s.erase(-1);
1493           *retPtr=(int)s.size();
1494         }
1495     }
1496   return ret.retn();
1497 }
1498
1499 /*!
1500  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1501  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1502  * 
1503  * \return a newly allocated array
1504  */
1505 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1506 {
1507   checkConnectivityFullyDefined();
1508   int nbOfCells=getNumberOfCells();
1509   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1510   ret->alloc(nbOfCells,1);
1511   int *retPtr=ret->getPointer();
1512   const int *conn=getNodalConnectivity()->getConstPointer();
1513   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1514   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1515     {
1516       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1517       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1518     }
1519   return ret.retn();
1520 }
1521
1522 /*!
1523  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1524  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1525  * array mean that the corresponding old node is no more used. 
1526  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1527  *           this->getNumberOfNodes() before call of this method. The caller is to
1528  *           delete this array using decrRef() as it is no more needed. 
1529  *  \throw If the coordinates array is not set.
1530  *  \throw If the nodal connectivity of cells is not defined.
1531  *  \throw If the nodal connectivity includes an invalid id.
1532  *
1533  *  \if ENABLE_EXAMPLES
1534  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1535  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1536  *  \endif
1537  */
1538 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1539 {
1540   return MEDCouplingPointSet::zipCoordsTraducer();
1541 }
1542
1543 /*!
1544  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1545  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1546  */
1547 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1548 {
1549   switch(compType)
1550     {
1551     case 0:
1552       return AreCellsEqual0(conn,connI,cell1,cell2);
1553     case 1:
1554       return AreCellsEqual1(conn,connI,cell1,cell2);
1555     case 2:
1556       return AreCellsEqual2(conn,connI,cell1,cell2);
1557     case 3:
1558       return AreCellsEqual3(conn,connI,cell1,cell2);
1559     case 7:
1560       return AreCellsEqual7(conn,connI,cell1,cell2);
1561     }
1562   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1563 }
1564
1565 /*!
1566  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1567  */
1568 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1569 {
1570   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1571     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1572   return 0;
1573 }
1574
1575 /*!
1576  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1577  */
1578 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1579 {
1580   int sz=connI[cell1+1]-connI[cell1];
1581   if(sz==connI[cell2+1]-connI[cell2])
1582     {
1583       if(conn[connI[cell1]]==conn[connI[cell2]])
1584         {
1585           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1586           unsigned dim=cm.getDimension();
1587           if(dim!=3)
1588             {
1589               if(dim!=1)
1590                 {
1591                   int sz1=2*(sz-1);
1592                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1593                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1594                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1595                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1596                   return work!=tmp+sz1?1:0;
1597                 }
1598               else
1599                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1600             }
1601           else
1602             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1603         }
1604     }
1605   return 0;
1606 }
1607
1608 /*!
1609  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1610  */
1611 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1612 {
1613   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1614     {
1615       if(conn[connI[cell1]]==conn[connI[cell2]])
1616         {
1617           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1618           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1619           return s1==s2?1:0;
1620         }
1621     }
1622   return 0;
1623 }
1624
1625 /*!
1626  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1627  */
1628 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1629 {
1630   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1631     {
1632       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1633       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1634       return s1==s2?1:0;
1635     }
1636   return 0;
1637 }
1638
1639 /*!
1640  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1641  */
1642 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1643 {
1644   int sz=connI[cell1+1]-connI[cell1];
1645   if(sz==connI[cell2+1]-connI[cell2])
1646     {
1647       if(conn[connI[cell1]]==conn[connI[cell2]])
1648         {
1649           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1650           unsigned dim=cm.getDimension();
1651           if(dim!=3)
1652             {
1653               if(dim!=1)
1654                 {
1655                   int sz1=2*(sz-1);
1656                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1657                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1658                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1659                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1660                   if(work!=tmp+sz1)
1661                     return 1;
1662                   else
1663                     {
1664                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1665                       std::reverse_iterator<int *> it2((int *)tmp);
1666                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1667                         return 2;
1668                       else
1669                         return 0;
1670                     }
1671                   
1672                   return work!=tmp+sz1?1:0;
1673                 }
1674               else
1675                 {//case of SEG2 and SEG3
1676                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1677                     return 1;
1678                   if(!cm.isQuadratic())
1679                     {
1680                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1681                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1682                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1683                         return 2;
1684                       return 0;
1685                     }
1686                   else
1687                     {
1688                       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])
1689                         return 2;
1690                       return 0;
1691                     }
1692                 }
1693             }
1694           else
1695             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1696         }
1697     }
1698   return 0;
1699 }
1700
1701 /*!
1702  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1703  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1704  * and result remains unchanged.
1705  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1706  * If in 'candidates' pool -1 value is considered as an empty value.
1707  * WARNING this method returns only ONE set of result !
1708  */
1709 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1710 {
1711   if(candidates.size()<1)
1712     return false;
1713   bool ret=false;
1714   std::vector<int>::const_iterator iter=candidates.begin();
1715   int start=(*iter++);
1716   for(;iter!=candidates.end();iter++)
1717     {
1718       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1719       if(status!=0)
1720         {
1721           if(!ret)
1722             {
1723               result->pushBackSilent(start);
1724               ret=true;
1725             }
1726           if(status==1)
1727             result->pushBackSilent(*iter);
1728           else
1729             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1730         }
1731     }
1732   return ret;
1733 }
1734
1735 /*!
1736  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1737  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1738  *
1739  * \param [in] compType input specifying the technique used to compare cells each other.
1740  *   - 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.
1741  *   - 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)
1742  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1743  *   - 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
1744  * can be used for users not sensitive to orientation of cell
1745  * \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.
1746  * \param [out] commonCells
1747  * \param [out] commonCellsI
1748  * \return the correspondance array old to new in a newly allocated array.
1749  * 
1750  */
1751 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1752 {
1753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1754   getReverseNodalConnectivity(revNodal,revNodalI);
1755   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1756 }
1757
1758 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1759                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1760 {
1761   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1762   int nbOfCells=nodalI->getNumberOfTuples()-1;
1763   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1764   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1765   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1766   std::vector<bool> isFetched(nbOfCells,false);
1767   if(startCellId==0)
1768     {
1769       for(int i=0;i<nbOfCells;i++)
1770         {
1771           if(!isFetched[i])
1772             {
1773               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1774               std::vector<int> v,v2;
1775               if(connOfNode!=connPtr+connIPtr[i+1])
1776                 {
1777                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1778                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1779                   connOfNode++;
1780                 }
1781               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1782                 if(*connOfNode>=0)
1783                   {
1784                     v=v2;
1785                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1786                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1787                     v2.resize(std::distance(v2.begin(),it));
1788                   }
1789               if(v2.size()>1)
1790                 {
1791                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1792                     {
1793                       int pos=commonCellsI->back();
1794                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1795                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1796                         isFetched[*it]=true;
1797                     }
1798                 }
1799             }
1800         }
1801     }
1802   else
1803     {
1804       for(int i=startCellId;i<nbOfCells;i++)
1805         {
1806           if(!isFetched[i])
1807             {
1808               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1809               std::vector<int> v,v2;
1810               if(connOfNode!=connPtr+connIPtr[i+1])
1811                 {
1812                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1813                   connOfNode++;
1814                 }
1815               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1816                 if(*connOfNode>=0)
1817                   {
1818                     v=v2;
1819                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1820                     v2.resize(std::distance(v2.begin(),it));
1821                   }
1822               if(v2.size()>1)
1823                 {
1824                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1825                     {
1826                       int pos=commonCellsI->back();
1827                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1828                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1829                         isFetched[*it]=true;
1830                     }
1831                 }
1832             }
1833         }
1834     }
1835   commonCellsArr=commonCells.retn();
1836   commonCellsIArr=commonCellsI.retn();
1837 }
1838
1839 /*!
1840  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1841  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1842  * than \a other->getNumberOfCells() in the returned array means that there is no
1843  * corresponding cell in \a this mesh.
1844  * It is expected that \a this and \a other meshes share the same node coordinates
1845  * array, if it is not so an exception is thrown. 
1846  *  \param [in] other - the mesh to compare with.
1847  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1848  *         valid values [0,1,2], see zipConnectivityTraducer().
1849  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1850  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1851  *         values. The caller is to delete this array using
1852  *         decrRef() as it is no more needed.
1853  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1854  *         mesh.
1855  *
1856  *  \if ENABLE_EXAMPLES
1857  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1858  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1859  *  \endif
1860  *  \sa checkDeepEquivalOnSameNodesWith()
1861  *  \sa checkGeoEquivalWith()
1862  */
1863 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1864 {
1865   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1866   int nbOfCells=getNumberOfCells();
1867   static const int possibleCompType[]={0,1,2};
1868   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1869     {
1870       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1871       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1872       oss << " !";
1873       throw INTERP_KERNEL::Exception(oss.str().c_str());
1874     }
1875   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1876   arr=o2n->substr(nbOfCells);
1877   arr->setName(other->getName());
1878   int tmp;
1879   if(other->getNumberOfCells()==0)
1880     return true;
1881   return arr->getMaxValue(tmp)<nbOfCells;
1882 }
1883
1884 /*!
1885  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1886  * This method tries to determine if \b other is fully included in \b this.
1887  * The main difference is that this method is not expected to throw exception.
1888  * This method has two outputs :
1889  *
1890  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1891  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1892  */
1893 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1894 {
1895   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1896   DataArrayInt *commonCells=0,*commonCellsI=0;
1897   int thisNbCells=getNumberOfCells();
1898   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1899   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1900   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1901   int otherNbCells=other->getNumberOfCells();
1902   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1903   arr2->alloc(otherNbCells,1);
1904   arr2->fillWithZero();
1905   int *arr2Ptr=arr2->getPointer();
1906   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1907   for(int i=0;i<nbOfCommon;i++)
1908     {
1909       int start=commonCellsPtr[commonCellsIPtr[i]];
1910       if(start<thisNbCells)
1911         {
1912           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1913             {
1914               int sig=commonCellsPtr[j]>0?1:-1;
1915               int val=std::abs(commonCellsPtr[j])-1;
1916               if(val>=thisNbCells)
1917                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1918             }
1919         }
1920     }
1921   arr2->setName(other->getName());
1922   if(arr2->presenceOfValue(0))
1923     return false;
1924   arr=arr2.retn();
1925   return true;
1926 }
1927
1928 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1929 {
1930   if(!other)
1931     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1932   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1933   if(!otherC)
1934     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1935   std::vector<const MEDCouplingUMesh *> ms(2);
1936   ms[0]=this;
1937   ms[1]=otherC;
1938   return MergeUMeshesOnSameCoords(ms);
1939 }
1940
1941 /*!
1942  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1943  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1944  * cellIds is not given explicitely but by a range python like.
1945  * 
1946  * \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.
1947  * \return a newly allocated
1948  * 
1949  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1950  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1951  */
1952 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1953 {
1954   if(getMeshDimension()!=-1)
1955     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1956   else
1957     {
1958       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1959       if(newNbOfCells!=1)
1960         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1961       if(start!=0)
1962         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1963       incrRef();
1964       return const_cast<MEDCouplingUMesh *>(this);
1965     }
1966 }
1967
1968 /*!
1969  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1970  * The result mesh shares or not the node coordinates array with \a this mesh depending
1971  * on \a keepCoords parameter.
1972  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1973  *           to write this mesh to the MED file, its cells must be sorted using
1974  *           sortCellsInMEDFileFrmt().
1975  *  \param [in] begin - an array of cell ids to include to the new mesh.
1976  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1977  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1978  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1979  *         by calling zipCoords().
1980  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1981  *         to delete this mesh using decrRef() as it is no more needed. 
1982  *  \throw If the coordinates array is not set.
1983  *  \throw If the nodal connectivity of cells is not defined.
1984  *  \throw If any cell id in the array \a begin is not valid.
1985  *
1986  *  \if ENABLE_EXAMPLES
1987  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1988  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1989  *  \endif
1990  */
1991 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1992 {
1993   if(getMeshDimension()!=-1)
1994     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1995   else
1996     {
1997       if(end-begin!=1)
1998         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1999       if(begin[0]!=0)
2000         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2001       incrRef();
2002       return const_cast<MEDCouplingUMesh *>(this);
2003     }
2004 }
2005
2006 /*!
2007  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2008  *
2009  * 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.
2010  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2011  * The number of cells of \b this will remain the same with this method.
2012  *
2013  * \param [in] begin begin of cell ids (included) of cells in this to assign
2014  * \param [in] end end of cell ids (excluded) of cells in this to assign
2015  * \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 ).
2016  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2017  */
2018 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2019 {
2020   checkConnectivityFullyDefined();
2021   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2022   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2023     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2024   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2025     {
2026       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2027       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2028       throw INTERP_KERNEL::Exception(oss.str().c_str());
2029     }
2030   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2031   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2032     {
2033       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2034       throw INTERP_KERNEL::Exception(oss.str().c_str());
2035     }
2036   int nbOfCells=getNumberOfCells();
2037   bool easyAssign=true;
2038   const int *connI=_nodal_connec_index->getConstPointer();
2039   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2040   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2041     {
2042       if(*it>=0 && *it<nbOfCells)
2043         {
2044           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2045         }
2046       else
2047         {
2048           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2049           throw INTERP_KERNEL::Exception(oss.str().c_str());
2050         }
2051     }
2052   if(easyAssign)
2053     {
2054       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2055       computeTypes();
2056     }
2057   else
2058     {
2059       DataArrayInt *arrOut=0,*arrIOut=0;
2060       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2061                                                arrOut,arrIOut);
2062       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2063       setConnectivity(arrOut,arrIOut,true);
2064     }
2065 }
2066
2067 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2068 {
2069   checkConnectivityFullyDefined();
2070   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2071   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2072     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2073   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2074     {
2075       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2076       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2077       throw INTERP_KERNEL::Exception(oss.str().c_str());
2078     }
2079   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2080   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2081     {
2082       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2083       throw INTERP_KERNEL::Exception(oss.str().c_str());
2084     }
2085   int nbOfCells=getNumberOfCells();
2086   bool easyAssign=true;
2087   const int *connI=_nodal_connec_index->getConstPointer();
2088   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2089   int it=start;
2090   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2091     {
2092       if(it>=0 && it<nbOfCells)
2093         {
2094           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2095         }
2096       else
2097         {
2098           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2099           throw INTERP_KERNEL::Exception(oss.str().c_str());
2100         }
2101     }
2102   if(easyAssign)
2103     {
2104       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2105       computeTypes();
2106     }
2107   else
2108     {
2109       DataArrayInt *arrOut=0,*arrIOut=0;
2110       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2111                                                 arrOut,arrIOut);
2112       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2113       setConnectivity(arrOut,arrIOut,true);
2114     }
2115 }                      
2116
2117 /*!
2118  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2119  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2120  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2121  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2122  *
2123  * \param [in] begin input start of array of node ids.
2124  * \param [in] end input end of array of node ids.
2125  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2126  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2127  */
2128 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2129 {
2130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2131   checkConnectivityFullyDefined();
2132   int tmp=-1;
2133   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2134   std::vector<bool> fastFinder(sz,false);
2135   for(const int *work=begin;work!=end;work++)
2136     if(*work>=0 && *work<sz)
2137       fastFinder[*work]=true;
2138   int nbOfCells=getNumberOfCells();
2139   const int *conn=getNodalConnectivity()->getConstPointer();
2140   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2141   for(int i=0;i<nbOfCells;i++)
2142     {
2143       int ref=0,nbOfHit=0;
2144       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2145         if(*work2>=0)
2146           {
2147             ref++;
2148             if(fastFinder[*work2])
2149               nbOfHit++;
2150           }
2151       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2152         cellIdsKept->pushBackSilent(i);
2153     }
2154   cellIdsKeptArr=cellIdsKept.retn();
2155 }
2156
2157 /*!
2158  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2159  * this->getMeshDimension(), that bound some cells of \a this mesh.
2160  * The cells of lower dimension to include to the result mesh are selected basing on
2161  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2162  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2163  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2164  * created mesh shares the node coordinates array with \a this mesh. 
2165  *  \param [in] begin - the array of node ids.
2166  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2167  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2168  *         array \a begin are added, else cells whose any node is in the
2169  *         array \a begin are added.
2170  *  \return MEDCouplingPointSet * - 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  *  \throw If any node id in \a begin is not valid.
2175  *
2176  *  \if ENABLE_EXAMPLES
2177  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2178  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2179  *  \endif
2180  */
2181 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2182 {
2183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2184   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2185   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2186   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2187   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2188 }
2189
2190 /*!
2191  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2192  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2193  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2194  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2195  *         by calling zipCoords().
2196  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2197  *         to delete this mesh using decrRef() as it is no more needed. 
2198  *  \throw If the coordinates array is not set.
2199  *  \throw If the nodal connectivity of cells is not defined.
2200  *
2201  *  \if ENABLE_EXAMPLES
2202  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2203  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2204  *  \endif
2205  */
2206 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2207 {
2208   DataArrayInt *desc=DataArrayInt::New();
2209   DataArrayInt *descIndx=DataArrayInt::New();
2210   DataArrayInt *revDesc=DataArrayInt::New();
2211   DataArrayInt *revDescIndx=DataArrayInt::New();
2212   //
2213   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2214   revDesc->decrRef();
2215   desc->decrRef();
2216   descIndx->decrRef();
2217   int nbOfCells=meshDM1->getNumberOfCells();
2218   const int *revDescIndxC=revDescIndx->getConstPointer();
2219   std::vector<int> boundaryCells;
2220   for(int i=0;i<nbOfCells;i++)
2221     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2222       boundaryCells.push_back(i);
2223   revDescIndx->decrRef();
2224   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2225   return ret;
2226 }
2227
2228 /*!
2229  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2230  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2231  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2232  */
2233 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2234 {
2235   checkFullyDefined();
2236   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2239   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2240   //
2241   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2242   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2243   //
2244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2245   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2246   const int *revDescPtr=revDesc->getConstPointer();
2247   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2248   int nbOfCells=getNumberOfCells();
2249   std::vector<bool> ret1(nbOfCells,false);
2250   int sz=0;
2251   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2252     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2253       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2254   //
2255   DataArrayInt *ret2=DataArrayInt::New();
2256   ret2->alloc(sz,1);
2257   int *ret2Ptr=ret2->getPointer();
2258   sz=0;
2259   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2260     if(*it)
2261       *ret2Ptr++=sz;
2262   ret2->setName("BoundaryCells");
2263   return ret2;
2264 }
2265
2266 /*!
2267  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2268  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2269  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2270  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2271  *
2272  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2273  * This method method returns cells ids set s = s1 + s2 where :
2274  * 
2275  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2276  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2277  *
2278  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2279  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2280  *
2281  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2282  * \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
2283  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2284  */
2285 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2286 {
2287   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2288     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2289   checkConnectivityFullyDefined();
2290   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2291   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2292     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2293   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2295   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2297   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2298   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2299   DataArrayInt *idsOtherInConsti=0;
2300   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2301   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2302   if(!b)
2303     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2304   std::set<int> s1;
2305   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2306     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2309   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2310   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2311   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2312   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2313   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2314   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2315   neighThisPartAuto=0;
2316   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2317   const int li[2]={0,1};
2318   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2319   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2321   s_renum1->sort();
2322   //
2323   cellIdsRk0=s0arr.retn();
2324   cellIdsRk1=s_renum1.retn();
2325 }
2326
2327 /*!
2328  * 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
2329  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2330  * 
2331  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2332  */
2333 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2334 {
2335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2339   //
2340   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2341   revDesc=0; desc=0; descIndx=0;
2342   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2344   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2345 }
2346
2347 /*!
2348  * Finds nodes lying on the boundary of \a this mesh.
2349  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2350  *          nodes. The caller is to delete this array using decrRef() as it is no
2351  *          more needed.
2352  *  \throw If the coordinates array is not set.
2353  *  \throw If the nodal connectivity of cells is node defined.
2354  *
2355  *  \if ENABLE_EXAMPLES
2356  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2357  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2358  *  \endif
2359  */
2360 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2361 {
2362   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2363   return skin->computeFetchedNodeIds();
2364 }
2365
2366 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2367 {
2368   incrRef();
2369   return const_cast<MEDCouplingUMesh *>(this);
2370 }
2371
2372 /*!
2373  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2374  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2375  * 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.
2376  * 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.
2377  * 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.
2378  *
2379  * \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
2380  *             parameter is altered during the call.
2381  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2382  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2383  * \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.
2384  *
2385  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2386  */
2387 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2388                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2389 {
2390   checkFullyDefined();
2391   otherDimM1OnSameCoords.checkFullyDefined();
2392   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2393     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2394   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2395     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2396   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2397   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2400   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2402   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2405   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2406   //
2407   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2409   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2410   DataArrayInt *idsTmp=0;
2411   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2413   if(!b)
2414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2415   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2416   DataArrayInt *tmp0=0,*tmp1=0;
2417   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2420   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2421   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2422   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2423   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2424   //
2425   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2426   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2427   nodeIdsToDuplicate=s3.retn();
2428 }
2429
2430 /*!
2431  * This method operates a modification of the connectivity and coords in \b this.
2432  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2433  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2434  * 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
2435  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2436  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2437  * 
2438  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2439  * 
2440  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2441  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2442  */
2443 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2444 {
2445   int nbOfNodes=getNumberOfNodes();
2446   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2447   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2448 }
2449
2450 /*!
2451  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2452  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2453  * This method is a generalization of shiftNodeNumbersInConn().
2454  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2455  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2456  *         this->getNumberOfNodes(), in "Old to New" mode. 
2457  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2458  *  \throw If the nodal connectivity of cells is not defined.
2459  *
2460  *  \if ENABLE_EXAMPLES
2461  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2462  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2463  *  \endif
2464  */
2465 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2466 {
2467   checkConnectivityFullyDefined();
2468   int *conn=getNodalConnectivity()->getPointer();
2469   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2470   int nbOfCells=getNumberOfCells();
2471   for(int i=0;i<nbOfCells;i++)
2472     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2473       {
2474         int& node=conn[iconn];
2475         if(node>=0)//avoid polyhedron separator
2476           {
2477             node=newNodeNumbersO2N[node];
2478           }
2479       }
2480   _nodal_connec->declareAsNew();
2481   updateTime();
2482 }
2483
2484 /*!
2485  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2486  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2487  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2488  * 
2489  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2490  */
2491 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2492 {
2493   checkConnectivityFullyDefined();
2494   int *conn=getNodalConnectivity()->getPointer();
2495   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2496   int nbOfCells=getNumberOfCells();
2497   for(int i=0;i<nbOfCells;i++)
2498     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2499       {
2500         int& node=conn[iconn];
2501         if(node>=0)//avoid polyhedron separator
2502           {
2503             node+=delta;
2504           }
2505       }
2506   _nodal_connec->declareAsNew();
2507   updateTime();
2508 }
2509
2510 /*!
2511  * This method operates a modification of the connectivity in \b this.
2512  * 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.
2513  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2514  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2515  * 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
2516  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2517  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2518  * 
2519  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2520  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2521  * 
2522  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2523  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2524  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2525  */
2526 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2527 {
2528   checkConnectivityFullyDefined();
2529   std::map<int,int> m;
2530   int val=offset;
2531   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2532     m[*work]=val;
2533   int *conn=getNodalConnectivity()->getPointer();
2534   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2535   int nbOfCells=getNumberOfCells();
2536   for(int i=0;i<nbOfCells;i++)
2537     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2538       {
2539         int& node=conn[iconn];
2540         if(node>=0)//avoid polyhedron separator
2541           {
2542             std::map<int,int>::iterator it=m.find(node);
2543             if(it!=m.end())
2544               node=(*it).second;
2545           }
2546       }
2547   updateTime();
2548 }
2549
2550 /*!
2551  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2552  *
2553  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2554  * After the call of this method the number of cells remains the same as before.
2555  *
2556  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2557  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2558  * be strictly in [0;this->getNumberOfCells()).
2559  *
2560  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2561  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2562  * should be contained in[0;this->getNumberOfCells()).
2563  * 
2564  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2565  */
2566 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2567 {
2568   checkConnectivityFullyDefined();
2569   int nbCells=getNumberOfCells();
2570   const int *array=old2NewBg;
2571   if(check)
2572     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2573   //
2574   const int *conn=_nodal_connec->getConstPointer();
2575   const int *connI=_nodal_connec_index->getConstPointer();
2576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2577   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2578   const int *n2oPtr=n2o->begin();
2579   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2580   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2581   newConn->copyStringInfoFrom(*_nodal_connec);
2582   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2583   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2584   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2585   //
2586   int *newC=newConn->getPointer();
2587   int *newCI=newConnI->getPointer();
2588   int loc=0;
2589   newCI[0]=loc;
2590   for(int i=0;i<nbCells;i++)
2591     {
2592       int pos=n2oPtr[i];
2593       int nbOfElts=connI[pos+1]-connI[pos];
2594       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2595       loc+=nbOfElts;
2596       newCI[i+1]=loc;
2597     }
2598   //
2599   setConnectivity(newConn,newConnI);
2600   if(check)
2601     free(const_cast<int *>(array));
2602 }
2603
2604 /*!
2605  * Finds cells whose bounding boxes intersect a given bounding box.
2606  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2607  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2608  *         zMax (if in 3D). 
2609  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2610  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2611  *         extent of the bounding box of cell to produce an addition to this bounding box.
2612  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2613  *         cells. The caller is to delete this array using decrRef() as it is no more
2614  *         needed. 
2615  *  \throw If the coordinates array is not set.
2616  *  \throw If the nodal connectivity of cells is not defined.
2617  *
2618  *  \if ENABLE_EXAMPLES
2619  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2620  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2621  *  \endif
2622  */
2623 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2624 {
2625   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2626   if(getMeshDimension()==-1)
2627     {
2628       elems->pushBackSilent(0);
2629       return elems.retn();
2630     }
2631   int dim=getSpaceDimension();
2632   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2633   const int* conn      = getNodalConnectivity()->getConstPointer();
2634   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2635   const double* coords = getCoords()->getConstPointer();
2636   int nbOfCells=getNumberOfCells();
2637   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2638     {
2639       for (int i=0; i<dim; i++)
2640         {
2641           elem_bb[i*2]=std::numeric_limits<double>::max();
2642           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2643         }
2644
2645       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2646         {
2647           int node= conn[inode];
2648           if(node>=0)//avoid polyhedron separator
2649             {
2650               for (int idim=0; idim<dim; idim++)
2651                 {
2652                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2653                     {
2654                       elem_bb[idim*2] = coords[node*dim+idim] ;
2655                     }
2656                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2657                     {
2658                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2659                     }
2660                 }
2661             }
2662         }
2663       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2664         elems->pushBackSilent(ielem);
2665     }
2666   return elems.retn();
2667 }
2668
2669 /*!
2670  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2671  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2672  * added in 'elems' parameter.
2673  */
2674 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2675 {
2676   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2677   if(getMeshDimension()==-1)
2678     {
2679       elems->pushBackSilent(0);
2680       return elems.retn();
2681     }
2682   int dim=getSpaceDimension();
2683   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2684   const int* conn      = getNodalConnectivity()->getConstPointer();
2685   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2686   const double* coords = getCoords()->getConstPointer();
2687   int nbOfCells=getNumberOfCells();
2688   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2689     {
2690       for (int i=0; i<dim; i++)
2691         {
2692           elem_bb[i*2]=std::numeric_limits<double>::max();
2693           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2694         }
2695
2696       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2697         {
2698           int node= conn[inode];
2699           if(node>=0)//avoid polyhedron separator
2700             {
2701               for (int idim=0; idim<dim; idim++)
2702                 {
2703                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2704                     {
2705                       elem_bb[idim*2] = coords[node*dim+idim] ;
2706                     }
2707                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2708                     {
2709                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2710                     }
2711                 }
2712             }
2713         }
2714       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2715         elems->pushBackSilent(ielem);
2716     }
2717   return elems.retn();
2718 }
2719
2720 /*!
2721  * Returns a type of a cell by its id.
2722  *  \param [in] cellId - the id of the cell of interest.
2723  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2724  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2725  */
2726 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2727 {
2728   const int *ptI=_nodal_connec_index->getConstPointer();
2729   const int *pt=_nodal_connec->getConstPointer();
2730   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2731     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2732   else
2733     {
2734       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2735       throw INTERP_KERNEL::Exception(oss.str().c_str());
2736     }
2737 }
2738
2739 /*!
2740  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2741  * This method does not throw exception if geometric type \a type is not in \a this.
2742  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2743  * The coordinates array is not considered here.
2744  *
2745  * \param [in] type the geometric type
2746  * \return cell ids in this having geometric type \a type.
2747  */
2748 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2749 {
2750   
2751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2752   ret->alloc(0,1);
2753   checkConnectivityFullyDefined();
2754   int nbCells=getNumberOfCells();
2755   int mdim=getMeshDimension();
2756   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2757   if(mdim!=(int)cm.getDimension())
2758     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2759   const int *ptI=_nodal_connec_index->getConstPointer();
2760   const int *pt=_nodal_connec->getConstPointer();
2761   for(int i=0;i<nbCells;i++)
2762     {
2763       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2764         ret->pushBackSilent(i);
2765     }
2766   return ret.retn();
2767 }
2768
2769 /*!
2770  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2771  */
2772 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2773 {
2774   const int *ptI=_nodal_connec_index->getConstPointer();
2775   const int *pt=_nodal_connec->getConstPointer();
2776   int nbOfCells=getNumberOfCells();
2777   int ret=0;
2778   for(int i=0;i<nbOfCells;i++)
2779     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2780       ret++;
2781   return ret;
2782 }
2783
2784 /*!
2785  * Returns the nodal connectivity of a given cell.
2786  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2787  * all returned node ids can be used in getCoordinatesOfNode().
2788  *  \param [in] cellId - an id of the cell of interest.
2789  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2790  *         cleared before the appending.
2791  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2792  */
2793 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2794 {
2795   const int *ptI=_nodal_connec_index->getConstPointer();
2796   const int *pt=_nodal_connec->getConstPointer();
2797   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2798     if(*w>=0)
2799       conn.push_back(*w);
2800 }
2801
2802 std::string MEDCouplingUMesh::simpleRepr() const
2803 {
2804   static const char msg0[]="No coordinates specified !";
2805   std::ostringstream ret;
2806   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2807   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2808   int tmpp1,tmpp2;
2809   double tt=getTime(tmpp1,tmpp2);
2810   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2811   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2812   if(_mesh_dim>=-1)
2813     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2814   else
2815     { ret << " Mesh dimension has not been set or is invalid !"; }
2816   if(_coords!=0)
2817     {
2818       const int spaceDim=getSpaceDimension();
2819       ret << spaceDim << "\nInfo attached on space dimension : ";
2820       for(int i=0;i<spaceDim;i++)
2821         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2822       ret << "\n";
2823     }
2824   else
2825     ret << msg0 << "\n";
2826   ret << "Number of nodes : ";
2827   if(_coords!=0)
2828     ret << getNumberOfNodes() << "\n";
2829   else
2830     ret << msg0 << "\n";
2831   ret << "Number of cells : ";
2832   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2833     ret << getNumberOfCells() << "\n";
2834   else
2835     ret << "No connectivity specified !" << "\n";
2836   ret << "Cell types present : ";
2837   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2838     {
2839       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2840       ret << cm.getRepr() << " ";
2841     }
2842   ret << "\n";
2843   return ret.str();
2844 }
2845
2846 std::string MEDCouplingUMesh::advancedRepr() const
2847 {
2848   std::ostringstream ret;
2849   ret << simpleRepr();
2850   ret << "\nCoordinates array : \n___________________\n\n";
2851   if(_coords)
2852     _coords->reprWithoutNameStream(ret);
2853   else
2854     ret << "No array set !\n";
2855   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2856   reprConnectivityOfThisLL(ret);
2857   return ret.str();
2858 }
2859
2860 /*!
2861  * This method returns a C++ code that is a dump of \a this.
2862  * This method will throw if this is not fully defined.
2863  */
2864 std::string MEDCouplingUMesh::cppRepr() const
2865 {
2866   static const char coordsName[]="coords";
2867   static const char connName[]="conn";
2868   static const char connIName[]="connI";
2869   checkFullyDefined();
2870   std::ostringstream ret; ret << "// coordinates" << std::endl;
2871   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2872   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2873   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2874   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2875   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2876   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2877   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2878   return ret.str();
2879 }
2880
2881 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2882 {
2883   std::ostringstream ret;
2884   reprConnectivityOfThisLL(ret);
2885   return ret.str();
2886 }
2887
2888 /*!
2889  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2890  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2891  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2892  * some algos).
2893  * 
2894  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2895  * 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
2896  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2897  */
2898 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2899 {
2900   int mdim=getMeshDimension();
2901   if(mdim<0)
2902     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2903   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2904   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2905   bool needToCpyCT=true;
2906   if(!_nodal_connec)
2907     {
2908       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2909       needToCpyCT=false;
2910     }
2911   else
2912     {
2913       tmp1=_nodal_connec;
2914       tmp1->incrRef();
2915     }
2916   if(!_nodal_connec_index)
2917     {
2918       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2919       needToCpyCT=false;
2920     }
2921   else
2922     {
2923       tmp2=_nodal_connec_index;
2924       tmp2->incrRef();
2925     }
2926   ret->setConnectivity(tmp1,tmp2,false);
2927   if(needToCpyCT)
2928     ret->_types=_types;
2929   if(!_coords)
2930     {
2931       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2932       ret->setCoords(coords);
2933     }
2934   else
2935     ret->setCoords(_coords);
2936   return ret.retn();
2937 }
2938
2939 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2940 {
2941   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2942     {
2943       int nbOfCells=getNumberOfCells();
2944       const int *c=_nodal_connec->getConstPointer();
2945       const int *ci=_nodal_connec_index->getConstPointer();
2946       for(int i=0;i<nbOfCells;i++)
2947         {
2948           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2949           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2950           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2951           stream << "\n";
2952         }
2953     }
2954   else
2955     stream << "Connectivity not defined !\n";
2956 }
2957
2958 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2959 {
2960   const int *ptI=_nodal_connec_index->getConstPointer();
2961   const int *pt=_nodal_connec->getConstPointer();
2962   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2963     return ptI[cellId+1]-ptI[cellId]-1;
2964   else
2965     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2966 }
2967
2968 /*!
2969  * Returns types of cells of the specified part of \a this mesh.
2970  * This method avoids computing sub-mesh explicitely to get its types.
2971  *  \param [in] begin - an array of cell ids of interest.
2972  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2973  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2974  *         describing the cell types. 
2975  *  \throw If the coordinates array is not set.
2976  *  \throw If the nodal connectivity of cells is not defined.
2977  *  \sa getAllGeoTypes()
2978  */
2979 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2980 {
2981   checkFullyDefined();
2982   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2983   const int *conn=_nodal_connec->getConstPointer();
2984   const int *connIndex=_nodal_connec_index->getConstPointer();
2985   for(const int *w=begin;w!=end;w++)
2986     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2987   return ret;
2988 }
2989
2990 /*!
2991  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2992  * a set of types of cells constituting \a this mesh. 
2993  * This method is for advanced users having prepared their connectivity before. For
2994  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2995  *  \param [in] conn - the nodal connectivity array. 
2996  *  \param [in] connIndex - the nodal connectivity index array.
2997  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2998  *         mesh is updated.
2999  */
3000 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3001 {
3002   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3003   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3004   if(isComputingTypes)
3005     computeTypes();
3006   declareAsNew();
3007 }
3008
3009 /*!
3010  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3011  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3012  */
3013 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3014                                                                                  _nodal_connec(0),_nodal_connec_index(0),
3015                                                                                 _types(other._types)
3016 {
3017   if(other._nodal_connec)
3018     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3019   if(other._nodal_connec_index)
3020     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3021 }
3022
3023 MEDCouplingUMesh::~MEDCouplingUMesh()
3024 {
3025   if(_nodal_connec)
3026     _nodal_connec->decrRef();
3027   if(_nodal_connec_index)
3028     _nodal_connec_index->decrRef();
3029 }
3030
3031 /*!
3032  * Recomputes a set of cell types of \a this mesh. For more info see
3033  * \ref MEDCouplingUMeshNodalConnectivity.
3034  */
3035 void MEDCouplingUMesh::computeTypes()
3036 {
3037   if(_nodal_connec && _nodal_connec_index)
3038     {
3039       _types.clear();
3040       const int *conn=_nodal_connec->getConstPointer();
3041       const int *connIndex=_nodal_connec_index->getConstPointer();
3042       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3043       if (nbOfElem > 0)
3044         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3045           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3046     }
3047 }
3048
3049 /*!
3050  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3051  */
3052 void MEDCouplingUMesh::checkFullyDefined() const
3053 {
3054   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3055     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3056 }
3057
3058 /*!
3059  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3060  */
3061 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3062 {
3063   if(!_nodal_connec_index || !_nodal_connec)
3064     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3065 }
3066
3067 /*!
3068  * Returns a number of cells constituting \a this mesh. 
3069  *  \return int - the number of cells in \a this mesh.
3070  *  \throw If the nodal connectivity of cells is not defined.
3071  */
3072 int MEDCouplingUMesh::getNumberOfCells() const
3073
3074   if(_nodal_connec_index)
3075     return _nodal_connec_index->getNumberOfTuples()-1;
3076   else
3077     if(_mesh_dim==-1)
3078       return 1;
3079     else
3080       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3081 }
3082
3083 /*!
3084  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3085  * mesh. For more info see \ref MEDCouplingMeshesPage.
3086  *  \return int - the dimension of \a this mesh.
3087  *  \throw If the mesh dimension is not defined using setMeshDimension().
3088  */
3089 int MEDCouplingUMesh::getMeshDimension() const
3090 {
3091   if(_mesh_dim<-1)
3092     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3093   return _mesh_dim;
3094 }
3095
3096 /*!
3097  * Returns a length of the nodal connectivity array.
3098  * This method is for test reason. Normally the integer returned is not useable by
3099  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3100  *  \return int - the length of the nodal connectivity array.
3101  */
3102 int MEDCouplingUMesh::getMeshLength() const
3103 {
3104   return _nodal_connec->getNbOfElems();
3105 }
3106
3107 /*!
3108  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3109  */
3110 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3111 {
3112   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3113   tinyInfo.push_back(getMeshDimension());
3114   tinyInfo.push_back(getNumberOfCells());
3115   if(_nodal_connec)
3116     tinyInfo.push_back(getMeshLength());
3117   else
3118     tinyInfo.push_back(-1);
3119 }
3120
3121 /*!
3122  * First step of unserialization process.
3123  */
3124 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3125 {
3126   return tinyInfo[6]<=0;
3127 }
3128
3129 /*!
3130  * Second step of serialization process.
3131  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3132  */
3133 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3134 {
3135   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3136   if(tinyInfo[5]!=-1)
3137     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3138 }
3139
3140 /*!
3141  * Third and final step of serialization process.
3142  */
3143 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3144 {
3145   MEDCouplingPointSet::serialize(a1,a2);
3146   if(getMeshDimension()>-1)
3147     {
3148       a1=DataArrayInt::New();
3149       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3150       int *ptA1=a1->getPointer();
3151       const int *conn=getNodalConnectivity()->getConstPointer();
3152       const int *index=getNodalConnectivityIndex()->getConstPointer();
3153       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3154       std::copy(conn,conn+getMeshLength(),ptA1);
3155     }
3156   else
3157     a1=0;
3158 }
3159
3160 /*!
3161  * Second and final unserialization process.
3162  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3163  */
3164 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3165 {
3166   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3167   setMeshDimension(tinyInfo[5]);
3168   if(tinyInfo[7]!=-1)
3169     {
3170       // Connectivity
3171       const int *recvBuffer=a1->getConstPointer();
3172       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3173       myConnecIndex->alloc(tinyInfo[6]+1,1);
3174       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3175       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3176       myConnec->alloc(tinyInfo[7],1);
3177       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3178       setConnectivity(myConnec, myConnecIndex);
3179     }
3180 }
3181
3182 /*!
3183  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3184  * CellIds are given using range specified by a start an end and step.
3185  */
3186 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3187 {
3188   checkFullyDefined();
3189   int ncell=getNumberOfCells();
3190   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3191   ret->_mesh_dim=_mesh_dim;
3192   ret->setCoords(_coords);
3193   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3194   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3195   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3196   int work=start;
3197   const int *conn=_nodal_connec->getConstPointer();
3198   const int *connIndex=_nodal_connec_index->getConstPointer();
3199   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3200     {
3201       if(work>=0 && work<ncell)
3202         {
3203           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3204         }
3205       else
3206         {
3207           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3208           throw INTERP_KERNEL::Exception(oss.str().c_str());
3209         }
3210     }
3211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3212   int *newConnPtr=newConn->getPointer();
3213   std::set<INTERP_KERNEL::NormalizedCellType> types;
3214   work=start;
3215   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3216     {
3217       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3218       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3219     }
3220   ret->setConnectivity(newConn,newConnI,false);
3221   ret->_types=types;
3222   ret->copyTinyInfoFrom(this);
3223   return ret.retn();
3224 }
3225
3226 /*!
3227  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3228  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3229  * The return newly allocated mesh will share the same coordinates as \a this.
3230  */
3231 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3232 {
3233   checkConnectivityFullyDefined();
3234   int ncell=getNumberOfCells();
3235   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3236   ret->_mesh_dim=_mesh_dim;
3237   ret->setCoords(_coords);
3238   std::size_t nbOfElemsRet=std::distance(begin,end);
3239   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3240   connIndexRet[0]=0;
3241   const int *conn=_nodal_connec->getConstPointer();
3242   const int *connIndex=_nodal_connec_index->getConstPointer();
3243   int newNbring=0;
3244   for(const int *work=begin;work!=end;work++,newNbring++)
3245     {
3246       if(*work>=0 && *work<ncell)
3247         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3248       else
3249         {
3250           free(connIndexRet);
3251           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3252           throw INTERP_KERNEL::Exception(oss.str().c_str());
3253         }
3254     }
3255   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3256   int *connRetWork=connRet;
3257   std::set<INTERP_KERNEL::NormalizedCellType> types;
3258   for(const int *work=begin;work!=end;work++)
3259     {
3260       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3261       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3262     }
3263   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3264   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3266   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3267   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3268   ret->_types=types;
3269   ret->copyTinyInfoFrom(this);
3270   return ret.retn();
3271 }
3272
3273 /*!
3274  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3275  * mesh.<br>
3276  * For 1D cells, the returned field contains lengths.<br>
3277  * For 2D cells, the returned field contains areas.<br>
3278  * For 3D cells, the returned field contains volumes.
3279  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3280  *         orientation, i.e. the volume is always positive.
3281  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3282  *         and one time . The caller is to delete this field using decrRef() as it is no
3283  *         more needed.
3284  */
3285 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3286 {
3287   std::string name="MeasureOfMesh_";
3288   name+=getName();
3289   int nbelem=getNumberOfCells();
3290   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3291   field->setName(name);
3292   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3293   array->alloc(nbelem,1);
3294   double *area_vol=array->getPointer();
3295   field->setArray(array) ; array=0;
3296   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3297   field->synchronizeTimeWithMesh();
3298   if(getMeshDimension()!=-1)
3299     {
3300       int ipt;
3301       INTERP_KERNEL::NormalizedCellType type;
3302       int dim_space=getSpaceDimension();
3303       const double *coords=getCoords()->getConstPointer();
3304       const int *connec=getNodalConnectivity()->getConstPointer();
3305       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3306       for(int iel=0;iel<nbelem;iel++)
3307         {
3308           ipt=connec_index[iel];
3309           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3310           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);
3311         }
3312       if(isAbs)
3313         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3314     }
3315   else
3316     {
3317       area_vol[0]=std::numeric_limits<double>::max();
3318     }
3319   return field.retn();
3320 }
3321
3322 /*!
3323  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3324  * mesh.<br>
3325  * For 1D cells, the returned array contains lengths.<br>
3326  * For 2D cells, the returned array contains areas.<br>
3327  * For 3D cells, the returned array contains volumes.
3328  * This method avoids building explicitly a part of \a this mesh to perform the work.
3329  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3330  *         orientation, i.e. the volume is always positive.
3331  *  \param [in] begin - an array of cell ids of interest.
3332  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3333  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3334  *          delete this array using decrRef() as it is no more needed.
3335  * 
3336  *  \if ENABLE_EXAMPLES
3337  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3338  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3339  *  \endif
3340  *  \sa getMeasureField()
3341  */
3342 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3343 {
3344   std::string name="PartMeasureOfMesh_";
3345   name+=getName();
3346   int nbelem=(int)std::distance(begin,end);
3347   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3348   array->setName(name);
3349   array->alloc(nbelem,1);
3350   double *area_vol=array->getPointer();
3351   if(getMeshDimension()!=-1)
3352     {
3353       int ipt;
3354       INTERP_KERNEL::NormalizedCellType type;
3355       int dim_space=getSpaceDimension();
3356       const double *coords=getCoords()->getConstPointer();
3357       const int *connec=getNodalConnectivity()->getConstPointer();
3358       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3359       for(const int *iel=begin;iel!=end;iel++)
3360         {
3361           ipt=connec_index[*iel];
3362           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3363           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3364         }
3365       if(isAbs)
3366         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3367     }
3368   else
3369     {
3370       area_vol[0]=std::numeric_limits<double>::max();
3371     }
3372   return array.retn();
3373 }
3374
3375 /*!
3376  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3377  * \a this one. The returned field contains the dual cell volume for each corresponding
3378  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3379  *  the dual mesh in P1 sens of \a this.<br>
3380  * For 1D cells, the returned field contains lengths.<br>
3381  * For 2D cells, the returned field contains areas.<br>
3382  * For 3D cells, the returned field contains volumes.
3383  * This method is useful to check "P1*" conservative interpolators.
3384  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3385  *         orientation, i.e. the volume is always positive.
3386  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3387  *          nodes and one time. The caller is to delete this array using decrRef() as
3388  *          it is no more needed.
3389  */
3390 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3391 {
3392   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3393   std::string name="MeasureOnNodeOfMesh_";
3394   name+=getName();
3395   int nbNodes=getNumberOfNodes();
3396   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3397   double cst=1./((double)getMeshDimension()+1.);
3398   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3399   array->alloc(nbNodes,1);
3400   double *valsToFill=array->getPointer();
3401   std::fill(valsToFill,valsToFill+nbNodes,0.);
3402   const double *values=tmp->getArray()->getConstPointer();
3403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3405   getReverseNodalConnectivity(da,daInd);
3406   const int *daPtr=da->getConstPointer();
3407   const int *daIPtr=daInd->getConstPointer();
3408   for(int i=0;i<nbNodes;i++)
3409     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3410       valsToFill[i]+=cst*values[*cell];
3411   ret->setMesh(this);
3412   ret->setArray(array);
3413   return ret.retn();
3414 }
3415
3416 /*!
3417  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3418  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3419  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3420  * and are normalized.
3421  * <br> \a this can be either 
3422  * - a  2D mesh in 2D or 3D space or 
3423  * - an 1D mesh in 2D space.
3424  * 
3425  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3426  *          cells and one time. The caller is to delete this field using decrRef() as
3427  *          it is no more needed.
3428  *  \throw If the nodal connectivity of cells is not defined.
3429  *  \throw If the coordinates array is not set.
3430  *  \throw If the mesh dimension is not set.
3431  *  \throw If the mesh and space dimension is not as specified above.
3432  */
3433 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3434 {
3435   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3436     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3437   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3438   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3439   int nbOfCells=getNumberOfCells();
3440   int nbComp=getMeshDimension()+1;
3441   array->alloc(nbOfCells,nbComp);
3442   double *vals=array->getPointer();
3443   const int *connI=_nodal_connec_index->getConstPointer();
3444   const int *conn=_nodal_connec->getConstPointer();
3445   const double *coords=_coords->getConstPointer();
3446   if(getMeshDimension()==2)
3447     {
3448       if(getSpaceDimension()==3)
3449         {
3450           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3451           const double *locPtr=loc->getConstPointer();
3452           for(int i=0;i<nbOfCells;i++,vals+=3)
3453             {
3454               int offset=connI[i];
3455               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3456               double n=INTERP_KERNEL::norm<3>(vals);
3457               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3458             }
3459         }
3460       else
3461         {
3462           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3463           const double *isAbsPtr=isAbs->getArray()->begin();
3464           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3465             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3466         }
3467     }
3468   else//meshdimension==1
3469     {
3470       double tmp[2];
3471       for(int i=0;i<nbOfCells;i++)
3472         {
3473           int offset=connI[i];
3474           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3475           double n=INTERP_KERNEL::norm<2>(tmp);
3476           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3477           *vals++=-tmp[1];
3478           *vals++=tmp[0];
3479         }
3480     }
3481   ret->setArray(array);
3482   ret->setMesh(this);
3483   ret->synchronizeTimeWithSupport();
3484   return ret.retn();
3485 }
3486
3487 /*!
3488  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3489  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3490  * and are normalized.
3491  * <br> \a this can be either 
3492  * - a  2D mesh in 2D or 3D space or 
3493  * - an 1D mesh in 2D space.
3494  * 
3495  * This method avoids building explicitly a part of \a this mesh to perform the work.
3496  *  \param [in] begin - an array of cell ids of interest.
3497  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3498  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3499  *          cells and one time. The caller is to delete this field using decrRef() as
3500  *          it is no more needed.
3501  *  \throw If the nodal connectivity of cells is not defined.
3502  *  \throw If the coordinates array is not set.
3503  *  \throw If the mesh dimension is not set.
3504  *  \throw If the mesh and space dimension is not as specified above.
3505  *  \sa buildOrthogonalField()
3506  *
3507  *  \if ENABLE_EXAMPLES
3508  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3509  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3510  *  \endif
3511  */
3512 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3513 {
3514   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3515     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3516   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3517   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3518   std::size_t nbelems=std::distance(begin,end);
3519   int nbComp=getMeshDimension()+1;
3520   array->alloc((int)nbelems,nbComp);
3521   double *vals=array->getPointer();
3522   const int *connI=_nodal_connec_index->getConstPointer();
3523   const int *conn=_nodal_connec->getConstPointer();
3524   const double *coords=_coords->getConstPointer();
3525   if(getMeshDimension()==2)
3526     {
3527       if(getSpaceDimension()==3)
3528         {
3529           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3530           const double *locPtr=loc->getConstPointer();
3531           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3532             {
3533               int offset=connI[*i];
3534               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3535               double n=INTERP_KERNEL::norm<3>(vals);
3536               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3537             }
3538         }
3539       else
3540         {
3541           for(std::size_t i=0;i<nbelems;i++)
3542             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3543         }
3544     }
3545   else//meshdimension==1
3546     {
3547       double tmp[2];
3548       for(const int *i=begin;i!=end;i++)
3549         {
3550           int offset=connI[*i];
3551           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3552           double n=INTERP_KERNEL::norm<2>(tmp);
3553           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3554           *vals++=-tmp[1];
3555           *vals++=tmp[0];
3556         }
3557     }
3558   ret->setArray(array);
3559   ret->setMesh(this);
3560   ret->synchronizeTimeWithSupport();
3561   return ret.retn();
3562 }
3563
3564 /*!
3565  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3566  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3567  * and are \b not normalized.
3568  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3569  *          cells and one time. The caller is to delete this field using decrRef() as
3570  *          it is no more needed.
3571  *  \throw If the nodal connectivity of cells is not defined.
3572  *  \throw If the coordinates array is not set.
3573  *  \throw If \a this->getMeshDimension() != 1.
3574  *  \throw If \a this mesh includes cells of type other than SEG2.
3575  */
3576 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3577 {
3578    if(getMeshDimension()!=1)
3579     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3580    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3581      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3582    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3583    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3584    int nbOfCells=getNumberOfCells();
3585    int spaceDim=getSpaceDimension();
3586    array->alloc(nbOfCells,spaceDim);
3587    double *pt=array->getPointer();
3588    const double *coo=getCoords()->getConstPointer();
3589    std::vector<int> conn;
3590    conn.reserve(2);
3591    for(int i=0;i<nbOfCells;i++)
3592      {
3593        conn.resize(0);
3594        getNodeIdsOfCell(i,conn);
3595        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3596      }
3597    ret->setArray(array);
3598    ret->setMesh(this);
3599    ret->synchronizeTimeWithSupport();
3600    return ret.retn();   
3601 }
3602
3603 /*!
3604  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3605  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3606  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3607  * from. If a result face is shared by two 3D cells, then the face in included twice in
3608  * the result mesh.
3609  *  \param [in] origin - 3 components of a point defining location of the plane.
3610  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3611  *         must be greater than 1e-6.
3612  *  \param [in] eps - half-thickness of the plane.
3613  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3614  *         producing correspondent 2D cells. The caller is to delete this array
3615  *         using decrRef() as it is no more needed.
3616  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3617  *         not share the node coordinates array with \a this mesh. The caller is to
3618  *         delete this mesh using decrRef() as it is no more needed.  
3619  *  \throw If the coordinates array is not set.
3620  *  \throw If the nodal connectivity of cells is not defined.
3621  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3622  *  \throw If magnitude of \a vec is less than 1e-6.
3623  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3624  *  \throw If \a this includes quadratic cells.
3625  */
3626 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3627 {
3628   checkFullyDefined();
3629   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3630     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3632   if(candidates->empty())
3633     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3634   std::vector<int> nodes;
3635   DataArrayInt *cellIds1D=0;
3636   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3637   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3639   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3640   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3641   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3642   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3643   revDesc2=0; revDescIndx2=0;
3644   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3645   revDesc1=0; revDescIndx1=0;
3646   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3648   //
3649   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3650   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3651     cut3DCurve[*it]=-1;
3652   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3653   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3654   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3655                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3656                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3657   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3658   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3659   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3660   if(cellIds2->empty())
3661     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3662   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3663   ret->setCoords(mDesc1->getCoords());
3664   ret->setConnectivity(conn,connI,true);
3665   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3666   return ret.retn();
3667 }
3668
3669 /*!
3670  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3671 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
3672 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3673 the result mesh.
3674  *  \param [in] origin - 3 components of a point defining location of the plane.
3675  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3676  *         must be greater than 1e-6.
3677  *  \param [in] eps - half-thickness of the plane.
3678  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3679  *         producing correspondent segments. The caller is to delete this array
3680  *         using decrRef() as it is no more needed.
3681  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3682  *         mesh in 3D space. This mesh does not share the node coordinates array with
3683  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3684  *         no more needed. 
3685  *  \throw If the coordinates array is not set.
3686  *  \throw If the nodal connectivity of cells is not defined.
3687  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3688  *  \throw If magnitude of \a vec is less than 1e-6.
3689  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3690  *  \throw If \a this includes quadratic cells.
3691  */
3692 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3693 {
3694   checkFullyDefined();
3695   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3696     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3698   if(candidates->empty())
3699     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3700   std::vector<int> nodes;
3701   DataArrayInt *cellIds1D=0;
3702   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3703   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3704   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3705   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3706   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3707   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3708   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3709   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3710   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3711   //
3712   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3713   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3714     cut3DCurve[*it]=-1;
3715   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3716   int ncellsSub=subMesh->getNumberOfCells();
3717   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3718   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3719                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3720                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3721   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3722   conn->alloc(0,1);
3723   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3724   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3725   for(int i=0;i<ncellsSub;i++)
3726     {
3727       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3728         {
3729           if(cut3DSurf[i].first!=-2)
3730             {
3731               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3732               connI->pushBackSilent(conn->getNumberOfTuples());
3733               cellIds2->pushBackSilent(i);
3734             }
3735           else
3736             {
3737               int cellId3DSurf=cut3DSurf[i].second;
3738               int offset=nodalI[cellId3DSurf]+1;
3739               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3740               for(int j=0;j<nbOfEdges;j++)
3741                 {
3742                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3743                   connI->pushBackSilent(conn->getNumberOfTuples());
3744                   cellIds2->pushBackSilent(cellId3DSurf);
3745                 }
3746             }
3747         }
3748     }
3749   if(cellIds2->empty())
3750     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3751   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3752   ret->setCoords(mDesc1->getCoords());
3753   ret->setConnectivity(conn,connI,true);
3754   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3755   return ret.retn();
3756 }
3757
3758 /*!
3759  * Finds cells whose bounding boxes intersect a given plane.
3760  *  \param [in] origin - 3 components of a point defining location of the plane.
3761  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3762  *         must be greater than 1e-6.
3763  *  \param [in] eps - half-thickness of the plane.
3764  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3765  *         cells. The caller is to delete this array using decrRef() as it is no more
3766  *         needed.
3767  *  \throw If the coordinates array is not set.
3768  *  \throw If the nodal connectivity of cells is not defined.
3769  *  \throw If \a this->getSpaceDimension() != 3.
3770  *  \throw If magnitude of \a vec is less than 1e-6.
3771  *  \sa buildSlice3D()
3772  */
3773 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3774 {
3775   checkFullyDefined();
3776   if(getSpaceDimension()!=3)
3777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3778   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3779   if(normm<1e-6)
3780     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3781   double vec2[3];
3782   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3783   double angle=acos(vec[2]/normm);
3784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3785   double bbox[6];
3786   if(angle>eps)
3787     {
3788       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3789       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3790       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3791       mw->setCoords(coo);
3792       mw->getBoundingBox(bbox);
3793       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3794       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3795     }
3796   else
3797     {
3798       getBoundingBox(bbox);
3799       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3800       cellIds=getCellsInBoundingBox(bbox,eps);
3801     }
3802   return cellIds.retn();
3803 }
3804
3805 /*!
3806  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3807  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3808  * No consideration of coordinate is done by this method.
3809  * 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)
3810  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3811  */
3812 bool MEDCouplingUMesh::isContiguous1D() const
3813 {
3814   if(getMeshDimension()!=1)
3815     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3816   int nbCells=getNumberOfCells();
3817   if(nbCells<1)
3818     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3819   const int *connI=_nodal_connec_index->getConstPointer();
3820   const int *conn=_nodal_connec->getConstPointer();
3821   int ref=conn[connI[0]+2];
3822   for(int i=1;i<nbCells;i++)
3823     {
3824       if(conn[connI[i]+1]!=ref)
3825         return false;
3826       ref=conn[connI[i]+2];
3827     }
3828   return true;
3829 }
3830
3831 /*!
3832  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3833  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3834  * \param pt reference point of the line
3835  * \param v normalized director vector of the line
3836  * \param eps max precision before throwing an exception
3837  * \param res output of size this->getNumberOfCells
3838  */
3839 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3840 {
3841   if(getMeshDimension()!=1)
3842     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3843    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3844      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3845    if(getSpaceDimension()!=3)
3846      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3847    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3848    const double *fPtr=f->getArray()->getConstPointer();
3849    double tmp[3];
3850    for(int i=0;i<getNumberOfCells();i++)
3851      {
3852        const double *tmp1=fPtr+3*i;
3853        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3854        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3855        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3856        double n1=INTERP_KERNEL::norm<3>(tmp);
3857        n1/=INTERP_KERNEL::norm<3>(tmp1);
3858        if(n1>eps)
3859          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3860      }
3861    const double *coo=getCoords()->getConstPointer();
3862    for(int i=0;i<getNumberOfNodes();i++)
3863      {
3864        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3865        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3866        res[i]=std::accumulate(tmp,tmp+3,0.);
3867      }
3868 }
3869
3870 /*!
3871  * 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. 
3872  * \a this is expected to be a mesh so that its space dimension is equal to its
3873  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3874  * 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).
3875  
3876  * 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
3877  * 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).
3878  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3879  *
3880  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3881  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3882  *
3883  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3884  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3885  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3886  * \return the positive value of the distance.
3887  * \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
3888  * dimension - 1.
3889  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3890  */
3891 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3892 {
3893   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3894   if(meshDim!=spaceDim-1)
3895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3896   if(meshDim!=2 && meshDim!=1)
3897     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3898   checkFullyDefined();
3899   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3900     { 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()); }
3901   DataArrayInt *ret1=0;
3902   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3903   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3904   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3905   cellId=*ret1Safe->begin();
3906   return *ret0->begin();
3907 }
3908
3909 /*!
3910  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3911  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3912  * 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
3913  * 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).
3914  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3915  * 
3916  * \a this is expected to be a mesh so that its space dimension is equal to its
3917  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3918  * 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).
3919  *
3920  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3921  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3922  *
3923  * \param [in] pts the list of points in which each tuple represents a point
3924  * \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.
3925  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3926  * \throw if number of components of \a pts is not equal to the space dimension.
3927  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3928  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3929  */
3930 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3931 {
3932   if(!pts)
3933     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3934   pts->checkAllocated();
3935   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3936   if(meshDim!=spaceDim-1)
3937     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3938   if(meshDim!=2 && meshDim!=1)
3939     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3940   if(pts->getNumberOfComponents()!=spaceDim)
3941     {
3942       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3943       throw INTERP_KERNEL::Exception(oss.str().c_str());
3944     }
3945   checkFullyDefined();
3946   int nbCells=getNumberOfCells();
3947   if(nbCells==0)
3948     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3949   int nbOfPts=pts->getNumberOfTuples();
3950   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3952   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3953   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3954   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3955   const double *bbox(bboxArr->begin());
3956   switch(spaceDim)
3957     {
3958     case 3:
3959       {
3960         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3961         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3962           {
3963             double x=std::numeric_limits<double>::max();
3964             std::vector<int> elems;
3965             myTree.getMinDistanceOfMax(ptsPtr,x);
3966             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3967             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3968           }
3969         break;
3970       }
3971     case 2:
3972       {
3973         BBTreeDst<2> myTree(bbox,0,0,nbCells);
3974         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3975           {
3976             double x=std::numeric_limits<double>::max();
3977             std::vector<int> elems;
3978             myTree.getMinDistanceOfMax(ptsPtr,x);
3979             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3980             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3981           }
3982         break;
3983       }
3984     default:
3985       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3986     }
3987   cellIds=ret1.retn();
3988   return ret0.retn();
3989 }
3990
3991 /*!
3992  * \param [in] pt the start pointer (included) of the coordinates of the point
3993  * \param [in] cellIdsBg the start pointer (included) of cellIds
3994  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3995  * \param [in] nc nodal connectivity
3996  * \param [in] ncI nodal connectivity index
3997  * \param [in,out] ret0 the min distance between \a this and the external input point
3998  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3999  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4000  */
4001 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)
4002 {
4003   cellId=-1;
4004   ret0=std::numeric_limits<double>::max();
4005   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4006     {
4007       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4008         {
4009         case INTERP_KERNEL::NORM_TRI3:
4010           {
4011             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4012             if(tmp<ret0)
4013               { ret0=tmp; cellId=*zeCell; }
4014             break;
4015           }
4016         case INTERP_KERNEL::NORM_QUAD4:
4017         case INTERP_KERNEL::NORM_POLYGON:
4018           {
4019             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4020             if(tmp<ret0)
4021               { ret0=tmp; cellId=*zeCell; }
4022             break;
4023           }
4024         default:
4025           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4026         }
4027     }
4028 }
4029
4030 /*!
4031  * \param [in] pt the start pointer (included) of the coordinates of the point
4032  * \param [in] cellIdsBg the start pointer (included) of cellIds
4033  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4034  * \param [in] nc nodal connectivity
4035  * \param [in] ncI nodal connectivity index
4036  * \param [in,out] ret0 the min distance between \a this and the external input point
4037  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4038  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4039  */
4040 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)
4041 {
4042   cellId=-1;
4043   ret0=std::numeric_limits<double>::max();
4044   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4045     {
4046        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4047         {
4048         case INTERP_KERNEL::NORM_SEG2:
4049           {
4050             std::size_t uselessEntry=0;
4051             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4052             tmp=sqrt(tmp);
4053             if(tmp<ret0)
4054               { ret0=tmp; cellId=*zeCell; }
4055             break;
4056           }
4057         default:
4058           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4059         }
4060     }
4061 }
4062
4063 /*!
4064  * Finds cells in contact with a ball (i.e. a point with precision). 
4065  * 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.
4066  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4067  *
4068  * \warning This method is suitable if the caller intends to evaluate only one
4069  *          point, for more points getCellsContainingPoints() is recommended as it is
4070  *          faster. 
4071  *  \param [in] pos - array of coordinates of the ball central point.
4072  *  \param [in] eps - ball radius.
4073  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4074  *         if there are no such cells.
4075  *  \throw If the coordinates array is not set.
4076  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4077  */
4078 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4079 {
4080   std::vector<int> elts;
4081   getCellsContainingPoint(pos,eps,elts);
4082   if(elts.empty())
4083     return -1;
4084   return elts.front();
4085 }
4086
4087 /*!
4088  * Finds cells in contact with a ball (i.e. a point with precision).
4089  * 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.
4090  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4091  * \warning This method is suitable if the caller intends to evaluate only one
4092  *          point, for more points getCellsContainingPoints() is recommended as it is
4093  *          faster. 
4094  *  \param [in] pos - array of coordinates of the ball central point.
4095  *  \param [in] eps - ball radius.
4096  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4097  *         before inserting ids.
4098  *  \throw If the coordinates array is not set.
4099  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4100  *
4101  *  \if ENABLE_EXAMPLES
4102  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4103  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4104  *  \endif
4105  */
4106 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4107 {
4108   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4109   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4110   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4111 }
4112
4113 /// @cond INTERNAL
4114
4115 namespace ParaMEDMEM
4116 {
4117   template<const int SPACEDIMM>
4118   class DummyClsMCUG
4119   {
4120   public:
4121     static const int MY_SPACEDIM=SPACEDIMM;
4122     static const int MY_MESHDIM=8;
4123     typedef int MyConnType;
4124     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4125     // begin
4126     // useless, but for windows compilation ...
4127     const double* getCoordinatesPtr() const { return 0; }
4128     const int* getConnectivityPtr() const { return 0; }
4129     const int* getConnectivityIndexPtr() const { return 0; }
4130     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4131     // end
4132   };
4133   
4134   /*!
4135    * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4136    */
4137   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map<INTERP_KERNEL::Node *,int>& m)
4138   {
4139     INTERP_KERNEL::Edge *ret=0;
4140     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]));
4141     m[n0]=bg[0]; m[n1]=bg[1];
4142     switch(typ)
4143       {
4144       case INTERP_KERNEL::NORM_SEG2:
4145         {
4146           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4147           break;
4148         }
4149       case INTERP_KERNEL::NORM_SEG3:
4150         {
4151           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4152           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4153           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4154           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4155           bool colinearity(inters.areColinears());
4156           delete e1; delete e2;
4157           if(colinearity)
4158             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4159           else
4160             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4161           break;
4162         }
4163       default:
4164         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4165       } 
4166     return ret;
4167   }
4168
4169   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4170   {
4171     INTERP_KERNEL::Edge *ret=0;
4172     switch(typ)
4173       {
4174       case INTERP_KERNEL::NORM_SEG2:
4175         {
4176           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4177           break;
4178         }
4179       case INTERP_KERNEL::NORM_SEG3:
4180         {
4181           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4182           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4183           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4184           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4185           bool colinearity=inters.areColinears();
4186           delete e1; delete e2;
4187           if(colinearity)
4188             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4189           else
4190             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4191           mapp2[bg[2]].second=false;
4192           break;
4193         }
4194       default:
4195         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4196       }
4197     return ret;
4198   }
4199
4200   /*!
4201    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4202    * the global mesh 'mDesc'.
4203    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4204    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4205    */
4206   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4207       std::map<INTERP_KERNEL::Node *,int>& mapp)
4208       throw(INTERP_KERNEL::Exception)
4209   {
4210     mapp.clear();
4211     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.
4212     const double *coo=mDesc->getCoords()->getConstPointer();
4213     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4214     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4215     std::set<int> s;
4216     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4217       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4218     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4219       {
4220         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4221         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4222       }
4223     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4224     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4225       {
4226         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4227         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4228       }
4229     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4230       {
4231         if((*it2).second.second)
4232           mapp[(*it2).second.first]=(*it2).first;
4233         ((*it2).second.first)->decrRef();
4234       }
4235     return ret;
4236   }
4237
4238   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4239   {
4240     if(nodeId>=offset2)
4241       {
4242         int locId=nodeId-offset2;
4243         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4244       }
4245     if(nodeId>=offset1)
4246       {
4247         int locId=nodeId-offset1;
4248         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4249       }
4250     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4251   }
4252
4253   /**
4254    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4255    */
4256   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4257                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4258                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4259   {
4260     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4261       {
4262         int eltId1=abs(*desc1)-1;
4263         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4264           {
4265             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4266             if(it==mappRev.end())
4267               {
4268                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4269                 mapp[node]=*it1;
4270                 mappRev[*it1]=node;
4271               }
4272           }
4273       }
4274   }
4275 }
4276
4277 /// @endcond
4278
4279 template<int SPACEDIM>
4280 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4281                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4282 {
4283   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4284   int *eltsIndexPtr(eltsIndex->getPointer());
4285   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4286   const double *bbox(bboxArr->begin());
4287   int nbOfCells=getNumberOfCells();
4288   const int *conn=_nodal_connec->getConstPointer();
4289   const int *connI=_nodal_connec_index->getConstPointer();
4290   double bb[2*SPACEDIM];
4291   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4292   for(int i=0;i<nbOfPoints;i++)
4293     {
4294       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4295       for(int j=0;j<SPACEDIM;j++)
4296         {
4297           bb[2*j]=pos[SPACEDIM*i+j];
4298           bb[2*j+1]=pos[SPACEDIM*i+j];
4299         }
4300       std::vector<int> candidates;
4301       myTree.getIntersectingElems(bb,candidates);
4302       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4303         {
4304           int sz(connI[(*iter)+1]-connI[*iter]-1);
4305           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4306           bool status(false);
4307           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4308             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4309           else
4310             {
4311               if(SPACEDIM!=2)
4312                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4313               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4314               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4315               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4316               INTERP_KERNEL::QuadraticPolygon *pol(0);
4317               for(int j=0;j<sz;j++)
4318                 {
4319                   int nodeId(conn[connI[*iter]+1+j]);
4320                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4321                 }
4322               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4323                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4324               else
4325                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4326               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4327               double a(0.),b(0.),c(0.);
4328               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4329               status=pol->isInOrOut2(n);
4330               delete pol; n->decrRef();
4331             }
4332           if(status)
4333             {
4334               eltsIndexPtr[i+1]++;
4335               elts->pushBackSilent(*iter);
4336             }
4337         }
4338     }
4339 }
4340 /*!
4341  * Finds cells in contact with several balls (i.e. points with precision).
4342  * This method is an extension of getCellContainingPoint() and
4343  * getCellsContainingPoint() for the case of multiple points.
4344  * 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.
4345  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4346  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4347  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4348  *         this->getSpaceDimension() * \a nbOfPoints 
4349  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4350  *  \param [in] eps - radius of balls (i.e. the precision).
4351  *  \param [out] elts - vector returning ids of found cells.
4352  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4353  *         dividing cell ids in \a elts into groups each referring to one
4354  *         point. Its every element (except the last one) is an index pointing to the
4355  *         first id of a group of cells. For example cells in contact with the *i*-th
4356  *         point are described by following range of indices:
4357  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4358  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4359  *         Number of cells in contact with the *i*-th point is
4360  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4361  *  \throw If the coordinates array is not set.
4362  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4363  *
4364  *  \if ENABLE_EXAMPLES
4365  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4366  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4367  *  \endif
4368  */
4369 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4370                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4371 {
4372   int spaceDim=getSpaceDimension();
4373   int mDim=getMeshDimension();
4374   if(spaceDim==3)
4375     {
4376       if(mDim==3)
4377         {
4378           const double *coords=_coords->getConstPointer();
4379           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4380         }
4381       /*else if(mDim==2)
4382         {
4383           
4384         }*/
4385       else
4386         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4387     }
4388   else if(spaceDim==2)
4389     {
4390       if(mDim==2)
4391         {
4392           const double *coords=_coords->getConstPointer();
4393           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4394         }
4395       else
4396         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4397     }
4398   else if(spaceDim==1)
4399     {
4400       if(mDim==1)
4401         {
4402           const double *coords=_coords->getConstPointer();
4403           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4404         }
4405       else
4406         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4407     }
4408   else
4409     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4410 }
4411
4412 /*!
4413  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4414  * least two its edges intersect each other anywhere except their extremities. An
4415  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4416  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4417  *         cleared before filling in.
4418  *  \param [in] eps - precision.
4419  *  \throw If \a this->getMeshDimension() != 2.
4420  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4421  */
4422 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4423 {
4424   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4425   if(getMeshDimension()!=2)
4426     throw INTERP_KERNEL::Exception(msg);
4427   int spaceDim=getSpaceDimension();
4428   if(spaceDim!=2 && spaceDim!=3)
4429     throw INTERP_KERNEL::Exception(msg);
4430   const int *conn=_nodal_connec->getConstPointer();
4431   const int *connI=_nodal_connec_index->getConstPointer();
4432   int nbOfCells=getNumberOfCells();
4433   std::vector<double> cell2DinS2;
4434   for(int i=0;i<nbOfCells;i++)
4435     {
4436       int offset=connI[i];
4437       int nbOfNodesForCell=connI[i+1]-offset-1;
4438       if(nbOfNodesForCell<=3)
4439         continue;
4440       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4441       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4442       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4443         cells.push_back(i);
4444       cell2DinS2.clear();
4445     }
4446 }
4447
4448 /*!
4449  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4450  *
4451  * 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.
4452  * 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.
4453  * 
4454  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4455  * This convex envelop is computed using Jarvis march algorithm.
4456  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4457  * 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)
4458  * 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.
4459  *
4460  * \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.
4461  */
4462 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4463 {
4464   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4465     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4466   checkFullyDefined();
4467   const double *coords=getCoords()->getConstPointer();
4468   int nbOfCells=getNumberOfCells();
4469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4470   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4472   int *workIndexOut=nodalConnecIndexOut->getPointer();
4473   *workIndexOut=0;
4474   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4475   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4476   std::set<INTERP_KERNEL::NormalizedCellType> types;
4477   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4478   isChanged->alloc(0,1);
4479   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4480     {
4481       int pos=nodalConnecOut->getNumberOfTuples();
4482       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4483         isChanged->pushBackSilent(i);
4484       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4485       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4486     }
4487   if(isChanged->empty())
4488     return 0;
4489   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4490   _types=types;
4491   return isChanged.retn();
4492 }
4493
4494 /*!
4495  * This method is \b NOT const because it can modify \a this.
4496  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4497  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4498  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4499  * \b 1 for translation and rotation around point of 'mesh1D'.
4500  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4501  */
4502 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4503 {
4504   checkFullyDefined();
4505   mesh1D->checkFullyDefined();
4506   if(!mesh1D->isContiguous1D())
4507     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4508   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4509     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4510   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4511     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4512   if(mesh1D->getMeshDimension()!=1)
4513     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4514   bool isQuad=false;
4515   if(isPresenceOfQuadratic())
4516     {
4517       if(mesh1D->isFullyQuadratic())
4518         isQuad=true;
4519       else
4520         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4521     }
4522   zipCoords();
4523   int oldNbOfNodes=getNumberOfNodes();
4524   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4525   switch(policy)
4526     {
4527     case 0:
4528       {
4529         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4530         break;
4531       }
4532     case 1:
4533       {
4534         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4535         break;
4536       }
4537     default:
4538       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4539     }
4540   setCoords(newCoords);
4541   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4542   updateTime();
4543   return ret.retn();
4544 }
4545
4546 /*!
4547  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4548  * If it is not the case an exception will be thrown.
4549  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4550  * intersection of plane defined by ('origin','vec').
4551  * This method has one in/out parameter : 'cut3DCurve'.
4552  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4553  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4554  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4555  * This method will throw an exception if \a this contains a non linear segment.
4556  */
4557 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4558 {
4559   checkFullyDefined();
4560   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4561     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4562   int ncells=getNumberOfCells();
4563   int nnodes=getNumberOfNodes();
4564   double vec2[3],vec3[3],vec4[3];
4565   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4566   if(normm<1e-6)
4567     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4568   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4569   const int *conn=_nodal_connec->getConstPointer();
4570   const int *connI=_nodal_connec_index->getConstPointer();
4571   const double *coo=_coords->getConstPointer();
4572   std::vector<double> addCoo;
4573   for(int i=0;i<ncells;i++)
4574     {
4575       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4576         {
4577           if(cut3DCurve[i]==-2)
4578             {
4579               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4580               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];
4581               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4582               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4583               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4584                 {
4585                   const double *st2=coo+3*st;
4586                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4587                   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]));
4588                   if(pos>eps && pos<1-eps)
4589                     {
4590                       int nNode=((int)addCoo.size())/3;
4591                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4592                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4593                       cut3DCurve[i]=nnodes+nNode;
4594                     }
4595                 }
4596             }
4597         }
4598       else
4599         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4600     }
4601   if(!addCoo.empty())
4602     {
4603       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4604       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4605       coo2->alloc(newNbOfNodes,3);
4606       double *tmp=coo2->getPointer();
4607       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4608       std::copy(addCoo.begin(),addCoo.end(),tmp);
4609       DataArrayDouble::SetArrayIn(coo2,_coords);
4610     }
4611 }
4612
4613 /*!
4614  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4615  * \param mesh1D is the input 1D mesh used for translation computation.
4616  * \return newCoords new coords filled by this method. 
4617  */
4618 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4619 {
4620   int oldNbOfNodes=getNumberOfNodes();
4621   int nbOf1DCells=mesh1D->getNumberOfCells();
4622   int spaceDim=getSpaceDimension();
4623   DataArrayDouble *ret=DataArrayDouble::New();
4624   std::vector<bool> isQuads;
4625   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4626   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4627   double *retPtr=ret->getPointer();
4628   const double *coords=getCoords()->getConstPointer();
4629   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4630   std::vector<int> v;
4631   std::vector<double> c;
4632   double vec[3];
4633   v.reserve(3);
4634   c.reserve(6);
4635   for(int i=0;i<nbOf1DCells;i++)
4636     {
4637       v.resize(0);
4638       mesh1D->getNodeIdsOfCell(i,v);
4639       c.resize(0);
4640       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4641       mesh1D->getCoordinatesOfNode(v[0],c);
4642       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4643       for(int j=0;j<oldNbOfNodes;j++)
4644         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4645       if(isQuad)
4646         {
4647           c.resize(0);
4648           mesh1D->getCoordinatesOfNode(v[1],c);
4649           mesh1D->getCoordinatesOfNode(v[0],c);
4650           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4651           for(int j=0;j<oldNbOfNodes;j++)
4652             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4653         }
4654     }
4655   ret->copyStringInfoFrom(*getCoords());
4656   return ret;
4657 }
4658
4659 /*!
4660  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4661  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4662  * \return newCoords new coords filled by this method. 
4663  */
4664 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4665 {
4666   if(mesh1D->getSpaceDimension()==2)
4667     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4668   if(mesh1D->getSpaceDimension()==3)
4669     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4670   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4671 }
4672
4673 /*!
4674  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4675  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4676  * \return newCoords new coords filled by this method. 
4677  */
4678 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4679 {
4680   if(isQuad)
4681     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4682   int oldNbOfNodes=getNumberOfNodes();
4683   int nbOf1DCells=mesh1D->getNumberOfCells();
4684   if(nbOf1DCells<2)
4685     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4686   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4687   int nbOfLevsInVec=nbOf1DCells+1;
4688   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4689   double *retPtr=ret->getPointer();
4690   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4691   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4692   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4693   tmp->setCoords(tmp2);
4694   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4695   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4696   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4697   for(int i=1;i<nbOfLevsInVec;i++)
4698     {
4699       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4700       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4701       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4702       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4703       tmp->translate(vec);
4704       double tmp3[2],radius,alpha,alpha0;
4705       const double *p0=i+1<nbOfLevsInVec?begin:third;
4706       const double *p1=i+1<nbOfLevsInVec?end:begin;
4707       const double *p2=i+1<nbOfLevsInVec?third:end;
4708       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4709       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]);
4710       double angle=acos(cosangle/(radius*radius));
4711       tmp->rotate(end,0,angle);
4712       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4713     }
4714   return ret.retn();
4715 }
4716
4717 /*!
4718  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4719  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4720  * \return newCoords new coords filled by this method. 
4721  */
4722 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4723 {
4724   if(isQuad)
4725     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4726   int oldNbOfNodes=getNumberOfNodes();
4727   int nbOf1DCells=mesh1D->getNumberOfCells();
4728   if(nbOf1DCells<2)
4729     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4730   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4731   int nbOfLevsInVec=nbOf1DCells+1;
4732   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4733   double *retPtr=ret->getPointer();
4734   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4735   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4736   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4737   tmp->setCoords(tmp2);
4738   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4739   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4740   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4741   for(int i=1;i<nbOfLevsInVec;i++)
4742     {
4743       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4744       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4745       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4746       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4747       tmp->translate(vec);
4748       double tmp3[2],radius,alpha,alpha0;
4749       const double *p0=i+1<nbOfLevsInVec?begin:third;
4750       const double *p1=i+1<nbOfLevsInVec?end:begin;
4751       const double *p2=i+1<nbOfLevsInVec?third:end;
4752       double vecPlane[3]={
4753         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4754         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4755         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4756       };
4757       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4758       if(norm>1.e-7)
4759         {
4760           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4761           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4762           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4763           double s2=norm2;
4764           double c2=cos(asin(s2));
4765           double m[3][3]={
4766             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4767             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4768             {-vec2[1]*s2, vec2[0]*s2, c2}
4769           };
4770           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]};
4771           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]};
4772           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]};
4773           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4774           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]);
4775           double angle=acos(cosangle/(radius*radius));
4776           tmp->rotate(end,vecPlane,angle);
4777           
4778         }
4779       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4780     }
4781   return ret.retn();
4782 }
4783
4784 /*!
4785  * This method is private because not easy to use for end user. This method is const contrary to
4786  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4787  * the coords sorted slice by slice.
4788  * \param isQuad specifies presence of quadratic cells.
4789  */
4790 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4791 {
4792   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4793   int nbOf2DCells=getNumberOfCells();
4794   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4795   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4796   const int *conn=_nodal_connec->getConstPointer();
4797   const int *connI=_nodal_connec_index->getConstPointer();
4798   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4799   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4800   newConnI->alloc(nbOf3DCells+1,1);
4801   int *newConnIPtr=newConnI->getPointer();
4802   *newConnIPtr++=0;
4803   std::vector<int> newc;
4804   for(int j=0;j<nbOf2DCells;j++)
4805     {
4806       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4807       *newConnIPtr++=(int)newc.size();
4808     }
4809   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4810   int *newConnPtr=newConn->getPointer();
4811   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4812   newConnIPtr=newConnI->getPointer();
4813   for(int iz=0;iz<nbOf1DCells;iz++)
4814     {
4815       if(iz!=0)
4816         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4817       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4818         {
4819           int icell=(int)(iter-newc.begin());
4820           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4821             {
4822               if(*iter!=-1)
4823                 *newConnPtr=(*iter)+iz*deltaPerLev;
4824               else
4825                 *newConnPtr=-1;
4826             }
4827           else
4828             *newConnPtr=(*iter);
4829         }
4830     }
4831   ret->setConnectivity(newConn,newConnI,true);
4832   ret->setCoords(getCoords());
4833   return ret;
4834 }
4835
4836 /*!
4837  * Checks if \a this mesh is constituted by only quadratic cells.
4838  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4839  *  \throw If the coordinates array is not set.
4840  *  \throw If the nodal connectivity of cells is not defined.
4841  */
4842 bool MEDCouplingUMesh::isFullyQuadratic() const
4843 {
4844   checkFullyDefined();
4845   bool ret=true;
4846   int nbOfCells=getNumberOfCells();
4847   for(int i=0;i<nbOfCells && ret;i++)
4848     {
4849       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4850       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4851       ret=cm.isQuadratic();
4852     }
4853   return ret;
4854 }
4855
4856 /*!
4857  * Checks if \a this mesh includes any quadratic cell.
4858  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4859  *  \throw If the coordinates array is not set.
4860  *  \throw If the nodal connectivity of cells is not defined.
4861  */
4862 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4863 {
4864   checkFullyDefined();
4865   bool ret=false;
4866   int nbOfCells=getNumberOfCells();
4867   for(int i=0;i<nbOfCells && !ret;i++)
4868     {
4869       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4870       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4871       ret=cm.isQuadratic();
4872     }
4873   return ret;
4874 }
4875
4876 /*!
4877  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4878  * this mesh, it remains unchanged.
4879  *  \throw If the coordinates array is not set.
4880  *  \throw If the nodal connectivity of cells is not defined.
4881  */
4882 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4883 {
4884   checkFullyDefined();
4885   int nbOfCells=getNumberOfCells();
4886   int delta=0;
4887   const int *iciptr=_nodal_connec_index->getConstPointer();
4888   for(int i=0;i<nbOfCells;i++)
4889     {
4890       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4891       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4892       if(cm.isQuadratic())
4893         {
4894           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4895           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4896           if(!cml.isDynamic())
4897             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4898           else
4899             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4900         }
4901     }
4902   if(delta==0)
4903     return ;
4904   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4905   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4906   const int *icptr=_nodal_connec->getConstPointer();
4907   newConn->alloc(getMeshLength()-delta,1);
4908   newConnI->alloc(nbOfCells+1,1);
4909   int *ocptr=newConn->getPointer();
4910   int *ociptr=newConnI->getPointer();
4911   *ociptr=0;
4912   _types.clear();
4913   for(int i=0;i<nbOfCells;i++,ociptr++)
4914     {
4915       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4916       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4917       if(!cm.isQuadratic())
4918         {
4919           _types.insert(type);
4920           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4921           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4922         }
4923       else
4924         {
4925           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4926           _types.insert(typel);
4927           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4928           int newNbOfNodes=cml.getNumberOfNodes();
4929           if(cml.isDynamic())
4930             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4931           *ocptr++=(int)typel;
4932           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4933           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4934         }
4935     }
4936   setConnectivity(newConn,newConnI,false);
4937 }
4938
4939 /*!
4940  * This method converts all linear cell in \a this to quadratic one.
4941  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4942  * 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)
4943  * 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.
4944  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4945  * end of the existing coordinates.
4946  * 
4947  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4948  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4949  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4950  * 
4951  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4952  *
4953  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4954  */
4955 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4956 {
4957   DataArrayInt *conn=0,*connI=0;
4958   DataArrayDouble *coords=0;
4959   std::set<INTERP_KERNEL::NormalizedCellType> types;
4960   checkFullyDefined();
4961   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4962   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4963   int meshDim=getMeshDimension();
4964   switch(conversionType)
4965     {
4966     case 0:
4967       switch(meshDim)
4968         {
4969         case 1:
4970           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4971           connSafe=conn; connISafe=connI; coordsSafe=coords;
4972           break;
4973         case 2:
4974           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4975           connSafe=conn; connISafe=connI; coordsSafe=coords;
4976           break;
4977         case 3:
4978           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4979           connSafe=conn; connISafe=connI; coordsSafe=coords;
4980           break;
4981         default:
4982           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4983         }
4984       break;
4985     case 1:
4986       {
4987         switch(meshDim)
4988         {
4989         case 1:
4990           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4991           connSafe=conn; connISafe=connI; coordsSafe=coords;
4992           break;
4993         case 2:
4994           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4995           connSafe=conn; connISafe=connI; coordsSafe=coords;
4996           break;
4997         case 3:
4998           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4999           connSafe=conn; connISafe=connI; coordsSafe=coords;
5000           break;
5001         default:
5002           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5003         }
5004         break;
5005       }
5006     default:
5007       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5008     }
5009   setConnectivity(connSafe,connISafe,false);
5010   _types=types;
5011   setCoords(coordsSafe);
5012   return ret.retn();
5013 }
5014
5015 /*!
5016  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5017  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5018  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5019  */
5020 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5021 {
5022   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5023   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5024   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5025   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5026   int nbOfCells=getNumberOfCells();
5027   int nbOfNodes=getNumberOfNodes();
5028   const int *cPtr=_nodal_connec->getConstPointer();
5029   const int *icPtr=_nodal_connec_index->getConstPointer();
5030   int lastVal=0,offset=nbOfNodes;
5031   for(int i=0;i<nbOfCells;i++,icPtr++)
5032     {
5033       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5034       if(type==INTERP_KERNEL::NORM_SEG2)
5035         {
5036           types.insert(INTERP_KERNEL::NORM_SEG3);
5037           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5038           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5039           newConn->pushBackSilent(offset++);
5040           lastVal+=4;
5041           newConnI->pushBackSilent(lastVal);
5042           ret->pushBackSilent(i);
5043         }
5044       else
5045         {
5046           types.insert(type);
5047           lastVal+=(icPtr[1]-icPtr[0]);
5048           newConnI->pushBackSilent(lastVal);
5049           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5050         }
5051     }
5052   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5053   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5054   return ret.retn();
5055 }
5056
5057 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
5058 {
5059   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5060   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5061   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5062   //
5063   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5064   DataArrayInt *conn1D=0,*conn1DI=0;
5065   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5066   DataArrayDouble *coordsTmp=0;
5067   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5068   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5069   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5070   const int *c1DPtr=conn1D->begin();
5071   const int *c1DIPtr=conn1DI->begin();
5072   int nbOfCells=getNumberOfCells();
5073   const int *cPtr=_nodal_connec->getConstPointer();
5074   const int *icPtr=_nodal_connec_index->getConstPointer();
5075   int lastVal=0;
5076   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5077     {
5078       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5079       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5080       if(!cm.isQuadratic())
5081         {
5082           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5083           types.insert(typ2); newConn->pushBackSilent(typ2);
5084           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5085           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5086             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5087           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5088           newConnI->pushBackSilent(lastVal);
5089           ret->pushBackSilent(i);
5090         }
5091       else
5092         {
5093           types.insert(typ);
5094           lastVal+=(icPtr[1]-icPtr[0]);
5095           newConnI->pushBackSilent(lastVal);
5096           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5097         }
5098     }
5099   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5100   return ret.retn();
5101 }
5102
5103 /*!
5104  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5105  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5106  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5107  */
5108 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5109 {
5110   
5111   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5112   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5113   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5114 }
5115
5116 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5117 {
5118   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5119   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5120   //
5121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5122   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5123   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5124   //
5125   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5126   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5127   DataArrayInt *conn1D=0,*conn1DI=0;
5128   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5129   DataArrayDouble *coordsTmp=0;
5130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5131   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5132   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5133   const int *c1DPtr=conn1D->begin();
5134   const int *c1DIPtr=conn1DI->begin();
5135   int nbOfCells=getNumberOfCells();
5136   const int *cPtr=_nodal_connec->getConstPointer();
5137   const int *icPtr=_nodal_connec_index->getConstPointer();
5138   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5139   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5140     {
5141       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5142       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5143       if(!cm.isQuadratic())
5144         {
5145           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5146           types.insert(typ2); newConn->pushBackSilent(typ2);
5147           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5148           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5149             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5150           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5151           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5152           newConnI->pushBackSilent(lastVal);
5153           ret->pushBackSilent(i);
5154         }
5155       else
5156         {
5157           types.insert(typ);
5158           lastVal+=(icPtr[1]-icPtr[0]);
5159           newConnI->pushBackSilent(lastVal);
5160           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5161         }
5162     }
5163   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5164   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5165   return ret.retn();
5166 }
5167
5168 /*!
5169  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5170  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5171  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5172  */
5173 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5174 {
5175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5176   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5177   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5178 }
5179
5180 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5181 {
5182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5183   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5184   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5185   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5186   //
5187   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5188   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5189   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5190   //
5191   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5192   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5193   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5194   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5195   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5196   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5197   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5198   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5200   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5202   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5203   int nbOfCells=getNumberOfCells();
5204   const int *cPtr=_nodal_connec->getConstPointer();
5205   const int *icPtr=_nodal_connec_index->getConstPointer();
5206   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5207   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5208     {
5209       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5210       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5211       if(!cm.isQuadratic())
5212         {
5213           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5214           if(typ2==INTERP_KERNEL::NORM_ERROR)
5215             {
5216               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5217               throw INTERP_KERNEL::Exception(oss.str().c_str());
5218             }
5219           types.insert(typ2); newConn->pushBackSilent(typ2);
5220           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5221           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5222             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5223           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5224             {
5225               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5226               int tmpPos=newConn->getNumberOfTuples();
5227               newConn->pushBackSilent(nodeId2);
5228               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5229             }
5230           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5231           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5232           newConnI->pushBackSilent(lastVal);
5233           ret->pushBackSilent(i);
5234         }
5235       else
5236         {
5237           types.insert(typ);
5238           lastVal+=(icPtr[1]-icPtr[0]);
5239           newConnI->pushBackSilent(lastVal);
5240           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5241         }
5242     }
5243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5245   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5246   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5247   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5248   int *c=newConn->getPointer();
5249   const int *cI(newConnI->begin());
5250   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5251     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5252   offset=coordsTmp2Safe->getNumberOfTuples();
5253   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5254     c[cI[(*elt)+1]-1]+=offset;
5255   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5256   return ret.retn();
5257 }
5258
5259 /*!
5260  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5261  * so that the number of cells remains the same. Quadratic faces are converted to
5262  * polygons. This method works only for 2D meshes in
5263  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5264  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5265  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5266  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5267  *         a polylinized edge constituting the input polygon.
5268  *  \throw If the coordinates array is not set.
5269  *  \throw If the nodal connectivity of cells is not defined.
5270  *  \throw If \a this->getMeshDimension() != 2.
5271  *  \throw If \a this->getSpaceDimension() != 2.
5272  */
5273 void MEDCouplingUMesh::tessellate2D(double eps)
5274 {
5275   checkFullyDefined();
5276   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5277     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5278   double epsa=fabs(eps);
5279   if(epsa<std::numeric_limits<double>::min())
5280     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 !");
5281   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5283   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5284   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5285   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5286   revDesc1=0; revDescIndx1=0;
5287   mDesc->tessellate2DCurve(eps);
5288   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5289   setCoords(mDesc->getCoords());
5290 }
5291
5292 /*!
5293  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5294  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5295  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5296  *         a sub-divided edge.
5297  *  \throw If the coordinates array is not set.
5298  *  \throw If the nodal connectivity of cells is not defined.
5299  *  \throw If \a this->getMeshDimension() != 1.
5300  *  \throw If \a this->getSpaceDimension() != 2.
5301  */
5302 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5303 {
5304   checkFullyDefined();
5305   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5306     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5307   double epsa=fabs(eps);
5308   if(epsa<std::numeric_limits<double>::min())
5309     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 !");
5310   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5311   int nbCells=getNumberOfCells();
5312   int nbNodes=getNumberOfNodes();
5313   const int *conn=_nodal_connec->getConstPointer();
5314   const int *connI=_nodal_connec_index->getConstPointer();
5315   const double *coords=_coords->getConstPointer();
5316   std::vector<double> addCoo;
5317   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5318   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5319   newConnI->alloc(nbCells+1,1);
5320   int *newConnIPtr=newConnI->getPointer();
5321   *newConnIPtr=0;
5322   int tmp1[3];
5323   INTERP_KERNEL::Node *tmp2[3];
5324   std::set<INTERP_KERNEL::NormalizedCellType> types;
5325   for(int i=0;i<nbCells;i++,newConnIPtr++)
5326     {
5327       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5328       if(cm.isQuadratic())
5329         {//assert(connI[i+1]-connI[i]-1==3)
5330           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5331           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5332           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5333           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5334           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5335           if(eac)
5336             {
5337               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5338               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5339               delete eac;
5340               newConnIPtr[1]=(int)newConn.size();
5341             }
5342           else
5343             {
5344               types.insert(INTERP_KERNEL::NORM_SEG2);
5345               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5346               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5347               newConnIPtr[1]=newConnIPtr[0]+3;
5348             }
5349         }
5350       else
5351         {
5352           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5353           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5354           newConnIPtr[1]=newConnIPtr[0]+3;
5355         }
5356     }
5357   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5358     return ;
5359   _types=types;
5360   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5362   newConnArr->alloc((int)newConn.size(),1);
5363   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5364   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5365   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5366   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5367   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5368   std::copy(addCoo.begin(),addCoo.end(),work);
5369   DataArrayDouble::SetArrayIn(newCoords,_coords);
5370   updateTime();
5371 }
5372
5373 /*!
5374  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5375  * In addition, returns an array mapping new cells to old ones. <br>
5376  * This method typically increases the number of cells in \a this mesh
5377  * but the number of nodes remains \b unchanged.
5378  * That's why the 3D splitting policies
5379  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5380  *  \param [in] policy - specifies a pattern used for splitting.
5381  * The semantic of \a policy is:
5382  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5383  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5384  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5385  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5386  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5387  *          an id of old cell producing it. The caller is to delete this array using
5388  *         decrRef() as it is no more needed. 
5389  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5390  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5391  *          and \a this->getMeshDimension() != 3. 
5392  *  \throw If \a policy is not one of the four discussed above.
5393  *  \throw If the nodal connectivity of cells is not defined.
5394  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5395  */
5396 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5397 {
5398   switch(policy)
5399     {
5400     case 0:
5401       return simplexizePol0();
5402     case 1:
5403       return simplexizePol1();
5404     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5405       return simplexizePlanarFace5();
5406     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5407       return simplexizePlanarFace6();
5408     default:
5409       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)");
5410     }
5411 }
5412
5413 /*!
5414  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5415  * - 1D: INTERP_KERNEL::NORM_SEG2
5416  * - 2D: INTERP_KERNEL::NORM_TRI3
5417  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5418  *
5419  * This method is useful for users that need to use P1 field services as
5420  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5421  * All these methods need mesh support containing only simplex cells.
5422  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5423  *  \throw If the coordinates array is not set.
5424  *  \throw If the nodal connectivity of cells is not defined.
5425  *  \throw If \a this->getMeshDimension() < 1.
5426  */
5427 bool MEDCouplingUMesh::areOnlySimplexCells() const
5428 {
5429   checkFullyDefined();
5430   int mdim=getMeshDimension();
5431   if(mdim<1 || mdim>3)
5432     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5433   int nbCells=getNumberOfCells();
5434   const int *conn=_nodal_connec->getConstPointer();
5435   const int *connI=_nodal_connec_index->getConstPointer();
5436   for(int i=0;i<nbCells;i++)
5437     {
5438       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5439       if(!cm.isSimplex())
5440         return false;
5441     }
5442   return true;
5443 }
5444
5445 /*!
5446  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5447  */
5448 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5449 {
5450   checkConnectivityFullyDefined();
5451   if(getMeshDimension()!=2)
5452     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5453   int nbOfCells=getNumberOfCells();
5454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5455   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5456   ret->alloc(nbOfCells+nbOfCutCells,1);
5457   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5458   int *retPt=ret->getPointer();
5459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5461   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5462   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5463   int *pt=newConn->getPointer();
5464   int *ptI=newConnI->getPointer();
5465   ptI[0]=0;
5466   const int *oldc=_nodal_connec->getConstPointer();
5467   const int *ci=_nodal_connec_index->getConstPointer();
5468   for(int i=0;i<nbOfCells;i++,ci++)
5469     {
5470       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5471         {
5472           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5473                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5474           pt=std::copy(tmp,tmp+8,pt);
5475           ptI[1]=ptI[0]+4;
5476           ptI[2]=ptI[0]+8;
5477           *retPt++=i;
5478           *retPt++=i;
5479           ptI+=2;
5480         }
5481       else
5482         {
5483           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5484           ptI[1]=ptI[0]+ci[1]-ci[0];
5485           ptI++;
5486           *retPt++=i;
5487         }
5488     }
5489   _nodal_connec->decrRef();
5490   _nodal_connec=newConn.retn();
5491   _nodal_connec_index->decrRef();
5492   _nodal_connec_index=newConnI.retn();
5493   computeTypes();
5494   updateTime();
5495   return ret.retn();
5496 }
5497
5498 /*!
5499  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5500  */
5501 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5502 {
5503   checkConnectivityFullyDefined();
5504   if(getMeshDimension()!=2)
5505     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5506   int nbOfCells=getNumberOfCells();
5507   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5508   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5509   ret->alloc(nbOfCells+nbOfCutCells,1);
5510   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5511   int *retPt=ret->getPointer();
5512   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5514   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5515   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5516   int *pt=newConn->getPointer();
5517   int *ptI=newConnI->getPointer();
5518   ptI[0]=0;
5519   const int *oldc=_nodal_connec->getConstPointer();
5520   const int *ci=_nodal_connec_index->getConstPointer();
5521   for(int i=0;i<nbOfCells;i++,ci++)
5522     {
5523       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5524         {
5525           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5526                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5527           pt=std::copy(tmp,tmp+8,pt);
5528           ptI[1]=ptI[0]+4;
5529           ptI[2]=ptI[0]+8;
5530           *retPt++=i;
5531           *retPt++=i;
5532           ptI+=2;
5533         }
5534       else
5535         {
5536           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5537           ptI[1]=ptI[0]+ci[1]-ci[0];
5538           ptI++;
5539           *retPt++=i;
5540         }
5541     }
5542   _nodal_connec->decrRef();
5543   _nodal_connec=newConn.retn();
5544   _nodal_connec_index->decrRef();
5545   _nodal_connec_index=newConnI.retn();
5546   computeTypes();
5547   updateTime();
5548   return ret.retn();
5549 }
5550
5551 /*!
5552  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5553  */
5554 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5555 {
5556   checkConnectivityFullyDefined();
5557   if(getMeshDimension()!=3)
5558     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5559   int nbOfCells=getNumberOfCells();
5560   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5561   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5562   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5563   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5564   int *retPt=ret->getPointer();
5565   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5566   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5567   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5568   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5569   int *pt=newConn->getPointer();
5570   int *ptI=newConnI->getPointer();
5571   ptI[0]=0;
5572   const int *oldc=_nodal_connec->getConstPointer();
5573   const int *ci=_nodal_connec_index->getConstPointer();
5574   for(int i=0;i<nbOfCells;i++,ci++)
5575     {
5576       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5577         {
5578           for(int j=0;j<5;j++,pt+=5,ptI++)
5579             {
5580               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5581               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];
5582               *retPt++=i;
5583               ptI[1]=ptI[0]+5;
5584             }
5585         }
5586       else
5587         {
5588           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5589           ptI[1]=ptI[0]+ci[1]-ci[0];
5590           ptI++;
5591           *retPt++=i;
5592         }
5593     }
5594   _nodal_connec->decrRef();
5595   _nodal_connec=newConn.retn();
5596   _nodal_connec_index->decrRef();
5597   _nodal_connec_index=newConnI.retn();
5598   computeTypes();
5599   updateTime();
5600   return ret.retn();
5601 }
5602
5603 /*!
5604  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5605  */
5606 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5607 {
5608   checkConnectivityFullyDefined();
5609   if(getMeshDimension()!=3)
5610     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5611   int nbOfCells=getNumberOfCells();
5612   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5613   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5614   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5615   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5616   int *retPt=ret->getPointer();
5617   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5618   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5619   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5620   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5621   int *pt=newConn->getPointer();
5622   int *ptI=newConnI->getPointer();
5623   ptI[0]=0;
5624   const int *oldc=_nodal_connec->getConstPointer();
5625   const int *ci=_nodal_connec_index->getConstPointer();
5626   for(int i=0;i<nbOfCells;i++,ci++)
5627     {
5628       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5629         {
5630           for(int j=0;j<6;j++,pt+=5,ptI++)
5631             {
5632               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5633               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];
5634               *retPt++=i;
5635               ptI[1]=ptI[0]+5;
5636             }
5637         }
5638       else
5639         {
5640           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5641           ptI[1]=ptI[0]+ci[1]-ci[0];
5642           ptI++;
5643           *retPt++=i;
5644         }
5645     }
5646   _nodal_connec->decrRef();
5647   _nodal_connec=newConn.retn();
5648   _nodal_connec_index->decrRef();
5649   _nodal_connec_index=newConnI.retn();
5650   computeTypes();
5651   updateTime();
5652   return ret.retn();
5653 }
5654
5655 /*!
5656  * 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.
5657  * This method completly ignore coordinates.
5658  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5659  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5660  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5661  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5662  */
5663 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5664 {
5665   checkFullyDefined();
5666   if(getMeshDimension()!=2)
5667     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5668   int nbOfCells=getNumberOfCells();
5669   int *connI=_nodal_connec_index->getPointer();
5670   int newConnLgth=0;
5671   for(int i=0;i<nbOfCells;i++,connI++)
5672     {
5673       int offset=descIndex[i];
5674       int nbOfEdges=descIndex[i+1]-offset;
5675       //
5676       bool ddirect=desc[offset+nbOfEdges-1]>0;
5677       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5678       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5679       for(int j=0;j<nbOfEdges;j++)
5680         {
5681           bool direct=desc[offset+j]>0;
5682           int edgeId=std::abs(desc[offset+j])-1;
5683           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5684             {
5685               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5686               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5687               int ref2=direct?id1:id2;
5688               if(ref==ref2)
5689                 {
5690                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5691                   newConnLgth+=nbOfSubNodes-1;
5692                   ref=direct?id2:id1;
5693                 }
5694               else
5695                 {
5696                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5697                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5698                 }
5699             }
5700           else
5701             {
5702               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5703             }
5704         }
5705       newConnLgth++;//+1 is for cell type
5706       connI[1]=newConnLgth;
5707     }
5708   //
5709   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5710   newConn->alloc(newConnLgth,1);
5711   int *work=newConn->getPointer();
5712   for(int i=0;i<nbOfCells;i++)
5713     {
5714       *work++=INTERP_KERNEL::NORM_POLYGON;
5715       int offset=descIndex[i];
5716       int nbOfEdges=descIndex[i+1]-offset;
5717       for(int j=0;j<nbOfEdges;j++)
5718         {
5719           bool direct=desc[offset+j]>0;
5720           int edgeId=std::abs(desc[offset+j])-1;
5721           if(direct)
5722             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5723           else
5724             {
5725               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5726               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5727               work=std::copy(it,it+nbOfSubNodes-1,work);
5728             }
5729         }
5730     }
5731   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5732   _types.clear();
5733   if(nbOfCells>0)
5734     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5735 }
5736
5737 /*!
5738  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5739  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5740  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5741  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5742  * so it can be useful to call mergeNodes() before calling this method.
5743  *  \throw If \a this->getMeshDimension() <= 1.
5744  *  \throw If the coordinates array is not set.
5745  *  \throw If the nodal connectivity of cells is not defined.
5746  */
5747 void MEDCouplingUMesh::convertDegeneratedCells()
5748 {
5749   checkFullyDefined();
5750   if(getMeshDimension()<=1)
5751     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5752   int nbOfCells=getNumberOfCells();
5753   if(nbOfCells<1)
5754     return ;
5755   int initMeshLgth=getMeshLength();
5756   int *conn=_nodal_connec->getPointer();
5757   int *index=_nodal_connec_index->getPointer();
5758   int posOfCurCell=0;
5759   int newPos=0;
5760   int lgthOfCurCell;
5761   for(int i=0;i<nbOfCells;i++)
5762     {
5763       lgthOfCurCell=index[i+1]-posOfCurCell;
5764       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5765       int newLgth;
5766       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5767                                                                                                      conn+newPos+1,newLgth);
5768       conn[newPos]=newType;
5769       newPos+=newLgth+1;
5770       posOfCurCell=index[i+1];
5771       index[i+1]=newPos;
5772     }
5773   if(newPos!=initMeshLgth)
5774     _nodal_connec->reAlloc(newPos);
5775   computeTypes();
5776 }
5777
5778 /*!
5779  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5780  * A cell is considered to be oriented correctly if an angle between its
5781  * normal vector and a given vector is less than \c PI / \c 2.
5782  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5783  *         cells. 
5784  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5785  *         checked.
5786  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5787  *         is not cleared before filling in.
5788  *  \throw If \a this->getMeshDimension() != 2.
5789  *  \throw If \a this->getSpaceDimension() != 3.
5790  *
5791  *  \if ENABLE_EXAMPLES
5792  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5793  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5794  *  \endif
5795  */
5796 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5797 {
5798   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5799     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5800   int nbOfCells=getNumberOfCells();
5801   const int *conn=_nodal_connec->getConstPointer();
5802   const int *connI=_nodal_connec_index->getConstPointer();
5803   const double *coordsPtr=_coords->getConstPointer();
5804   for(int i=0;i<nbOfCells;i++)
5805     {
5806       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5807       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5808         {
5809           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5810           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5811             cells.push_back(i);
5812         }
5813     }
5814 }
5815
5816 /*!
5817  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5818  * considered to be oriented correctly if an angle between its normal vector and a
5819  * given vector is less than \c PI / \c 2. 
5820  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5821  *         cells. 
5822  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5823  *         checked.
5824  *  \throw If \a this->getMeshDimension() != 2.
5825  *  \throw If \a this->getSpaceDimension() != 3.
5826  *
5827  *  \if ENABLE_EXAMPLES
5828  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5829  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5830  *  \endif
5831  */
5832 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5833 {
5834   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5835     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5836   int nbOfCells=getNumberOfCells();
5837   int *conn=_nodal_connec->getPointer();
5838   const int *connI=_nodal_connec_index->getConstPointer();
5839   const double *coordsPtr=_coords->getConstPointer();
5840   bool isModified=false;
5841   for(int i=0;i<nbOfCells;i++)
5842     {
5843       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5844       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5845         {
5846           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5847           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5848             {
5849               isModified=true;
5850               if(!isQuadratic)
5851                 {
5852                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5853                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5854                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5855                 }
5856               else
5857                 {
5858                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5859                   std::vector<int> tmp0(sz-1),tmp1(sz);
5860                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5861                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5862                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5863                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5864                 }
5865             }
5866         }
5867     }
5868   if(isModified)
5869     _nodal_connec->declareAsNew();
5870   updateTime();
5871 }
5872
5873 /*!
5874  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5875  * oriented facets. The normal vector of the facet should point out of the cell.
5876  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5877  *         is not cleared before filling in.
5878  *  \throw If \a this->getMeshDimension() != 3.
5879  *  \throw If \a this->getSpaceDimension() != 3.
5880  *  \throw If the coordinates array is not set.
5881  *  \throw If the nodal connectivity of cells is not defined.
5882  *
5883  *  \if ENABLE_EXAMPLES
5884  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5885  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5886  *  \endif
5887  */
5888 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5889 {
5890   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5891     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5892   int nbOfCells=getNumberOfCells();
5893   const int *conn=_nodal_connec->getConstPointer();
5894   const int *connI=_nodal_connec_index->getConstPointer();
5895   const double *coordsPtr=_coords->getConstPointer();
5896   for(int i=0;i<nbOfCells;i++)
5897     {
5898       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5899       if(type==INTERP_KERNEL::NORM_POLYHED)
5900         {
5901           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5902             cells.push_back(i);
5903         }
5904     }
5905 }
5906
5907 /*!
5908  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5909  * out of the cell. 
5910  *  \throw If \a this->getMeshDimension() != 3.
5911  *  \throw If \a this->getSpaceDimension() != 3.
5912  *  \throw If the coordinates array is not set.
5913  *  \throw If the nodal connectivity of cells is not defined.
5914  *  \throw If the reparation fails.
5915  *
5916  *  \if ENABLE_EXAMPLES
5917  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5918  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5919  *  \endif
5920  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5921  */
5922 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5923 {
5924   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5925     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5926   int nbOfCells=getNumberOfCells();
5927   int *conn=_nodal_connec->getPointer();
5928   const int *connI=_nodal_connec_index->getConstPointer();
5929   const double *coordsPtr=_coords->getConstPointer();
5930   for(int i=0;i<nbOfCells;i++)
5931     {
5932       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5933       if(type==INTERP_KERNEL::NORM_POLYHED)
5934         {
5935           try
5936             {
5937               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5938                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5939             }
5940           catch(INTERP_KERNEL::Exception& e)
5941             {
5942               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5943               throw INTERP_KERNEL::Exception(oss.str().c_str());
5944             }
5945         }
5946     }
5947   updateTime();
5948 }
5949
5950 /*!
5951  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5952  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5953  * according to which the first facet of the cell should be oriented to have the normal vector
5954  * pointing out of cell.
5955  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5956  *         cells. The caller is to delete this array using decrRef() as it is no more
5957  *         needed. 
5958  *  \throw If \a this->getMeshDimension() != 3.
5959  *  \throw If \a this->getSpaceDimension() != 3.
5960  *  \throw If the coordinates array is not set.
5961  *  \throw If the nodal connectivity of cells is not defined.
5962  *
5963  *  \if ENABLE_EXAMPLES
5964  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5965  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5966  *  \endif
5967  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5968  */
5969 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5970 {
5971   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5972   if(getMeshDimension()!=3)
5973     throw INTERP_KERNEL::Exception(msg);
5974   int spaceDim=getSpaceDimension();
5975   if(spaceDim!=3)
5976     throw INTERP_KERNEL::Exception(msg);
5977   //
5978   int nbOfCells=getNumberOfCells();
5979   int *conn=_nodal_connec->getPointer();
5980   const int *connI=_nodal_connec_index->getConstPointer();
5981   const double *coo=getCoords()->getConstPointer();
5982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5983   for(int i=0;i<nbOfCells;i++)
5984     {
5985       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5986       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5987         {
5988           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5989             {
5990               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5991               cells->pushBackSilent(i);
5992             }
5993         }
5994     }
5995   return cells.retn();
5996 }
5997
5998 /*!
5999  * This method is a faster method to correct orientation of all 3D cells in \a this.
6000  * 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.
6001  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6002  * 
6003  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6004  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6005  */
6006 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6007 {
6008   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6009     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6010   int nbOfCells=getNumberOfCells();
6011   int *conn=_nodal_connec->getPointer();
6012   const int *connI=_nodal_connec_index->getConstPointer();
6013   const double *coordsPtr=_coords->getConstPointer();
6014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6015   for(int i=0;i<nbOfCells;i++)
6016     {
6017       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6018       switch(type)
6019         {
6020         case INTERP_KERNEL::NORM_TETRA4:
6021           {
6022             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6023               {
6024                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6025                 ret->pushBackSilent(i);
6026               }
6027             break;
6028           }
6029         case INTERP_KERNEL::NORM_PYRA5:
6030           {
6031             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6032               {
6033                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6034                 ret->pushBackSilent(i);
6035               }
6036             break;
6037           }
6038         case INTERP_KERNEL::NORM_PENTA6:
6039         case INTERP_KERNEL::NORM_HEXA8:
6040         case INTERP_KERNEL::NORM_HEXGP12:
6041           {
6042             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6043               {
6044                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6045                 ret->pushBackSilent(i);
6046               }
6047             break;
6048           }
6049         case INTERP_KERNEL::NORM_POLYHED:
6050           {
6051             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6052               {
6053                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6054                 ret->pushBackSilent(i);
6055               }
6056             break;
6057           }
6058         default:
6059           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 !");
6060         }
6061     }
6062   updateTime();
6063   return ret.retn();
6064 }
6065
6066 /*!
6067  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6068  * If it is not the case an exception will be thrown.
6069  * This method is fast because the first cell of \a this is used to compute the plane.
6070  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6071  * \param pos output of size at least 3 used to store a point owned of searched plane.
6072  */
6073 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6074 {
6075   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6076     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6077   const int *conn=_nodal_connec->getConstPointer();
6078   const int *connI=_nodal_connec_index->getConstPointer();
6079   const double *coordsPtr=_coords->getConstPointer();
6080   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6081   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6082 }
6083
6084 /*!
6085  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6086  * cells. Currently cells of the following types are treated:
6087  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6088  * For a cell of other type an exception is thrown.
6089  * Space dimension of a 2D mesh can be either 2 or 3.
6090  * The Edge Ratio of a cell \f$t\f$ is: 
6091  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6092  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6093  *  the smallest edge lengths of \f$t\f$.
6094  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6095  *          cells and one time, lying on \a this mesh. The caller is to delete this
6096  *          field using decrRef() as it is no more needed. 
6097  *  \throw If the coordinates array is not set.
6098  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6099  *  \throw If the connectivity data array has more than one component.
6100  *  \throw If the connectivity data array has a named component.
6101  *  \throw If the connectivity index data array has more than one component.
6102  *  \throw If the connectivity index data array has a named component.
6103  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6104  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6105  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6106  */
6107 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6108 {
6109   checkCoherency();
6110   int spaceDim=getSpaceDimension();
6111   int meshDim=getMeshDimension();
6112   if(spaceDim!=2 && spaceDim!=3)
6113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6114   if(meshDim!=2 && meshDim!=3)
6115     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6116   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6117   ret->setMesh(this);
6118   int nbOfCells=getNumberOfCells();
6119   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6120   arr->alloc(nbOfCells,1);
6121   double *pt=arr->getPointer();
6122   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6123   const int *conn=_nodal_connec->getConstPointer();
6124   const int *connI=_nodal_connec_index->getConstPointer();
6125   const double *coo=_coords->getConstPointer();
6126   double tmp[12];
6127   for(int i=0;i<nbOfCells;i++,pt++)
6128     {
6129       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6130       switch(t)
6131         {
6132           case INTERP_KERNEL::NORM_TRI3:
6133             {
6134               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6135               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6136               break;
6137             }
6138           case INTERP_KERNEL::NORM_QUAD4:
6139             {
6140               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6141               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6142               break;
6143             }
6144           case INTERP_KERNEL::NORM_TETRA4:
6145             {
6146               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6147               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6148               break;
6149             }
6150         default:
6151           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6152         }
6153       conn+=connI[i+1]-connI[i];
6154     }
6155   ret->setName("EdgeRatio");
6156   ret->synchronizeTimeWithSupport();
6157   return ret.retn();
6158 }
6159
6160 /*!
6161  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6162  * cells. Currently cells of the following types are treated:
6163  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6164  * For a cell of other type an exception is thrown.
6165  * Space dimension of a 2D mesh can be either 2 or 3.
6166  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6167  *          cells and one time, lying on \a this mesh. The caller is to delete this
6168  *          field using decrRef() as it is no more needed. 
6169  *  \throw If the coordinates array is not set.
6170  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6171  *  \throw If the connectivity data array has more than one component.
6172  *  \throw If the connectivity data array has a named component.
6173  *  \throw If the connectivity index data array has more than one component.
6174  *  \throw If the connectivity index data array has a named component.
6175  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6176  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6177  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6178  */
6179 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6180 {
6181   checkCoherency();
6182   int spaceDim=getSpaceDimension();
6183   int meshDim=getMeshDimension();
6184   if(spaceDim!=2 && spaceDim!=3)
6185     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6186   if(meshDim!=2 && meshDim!=3)
6187     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6188   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6189   ret->setMesh(this);
6190   int nbOfCells=getNumberOfCells();
6191   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6192   arr->alloc(nbOfCells,1);
6193   double *pt=arr->getPointer();
6194   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6195   const int *conn=_nodal_connec->getConstPointer();
6196   const int *connI=_nodal_connec_index->getConstPointer();
6197   const double *coo=_coords->getConstPointer();
6198   double tmp[12];
6199   for(int i=0;i<nbOfCells;i++,pt++)
6200     {
6201       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6202       switch(t)
6203         {
6204           case INTERP_KERNEL::NORM_TRI3:
6205             {
6206               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6207               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6208               break;
6209             }
6210           case INTERP_KERNEL::NORM_QUAD4:
6211             {
6212               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6213               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6214               break;
6215             }
6216           case INTERP_KERNEL::NORM_TETRA4:
6217             {
6218               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6219               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6220               break;
6221             }
6222         default:
6223           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6224         }
6225       conn+=connI[i+1]-connI[i];
6226     }
6227   ret->setName("AspectRatio");
6228   ret->synchronizeTimeWithSupport();
6229   return ret.retn();
6230 }
6231
6232 /*!
6233  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6234  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6235  * treated: INTERP_KERNEL::NORM_QUAD4.
6236  * For a cell of other type an exception is thrown.
6237  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6238  *          cells and one time, lying on \a this mesh. The caller is to delete this
6239  *          field using decrRef() as it is no more needed. 
6240  *  \throw If the coordinates array is not set.
6241  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6242  *  \throw If the connectivity data array has more than one component.
6243  *  \throw If the connectivity data array has a named component.
6244  *  \throw If the connectivity index data array has more than one component.
6245  *  \throw If the connectivity index data array has a named component.
6246  *  \throw If \a this->getMeshDimension() != 2.
6247  *  \throw If \a this->getSpaceDimension() != 3.
6248  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6249  */
6250 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6251 {
6252   checkCoherency();
6253   int spaceDim=getSpaceDimension();
6254   int meshDim=getMeshDimension();
6255   if(spaceDim!=3)
6256     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6257   if(meshDim!=2)
6258     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6259   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6260   ret->setMesh(this);
6261   int nbOfCells=getNumberOfCells();
6262   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6263   arr->alloc(nbOfCells,1);
6264   double *pt=arr->getPointer();
6265   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6266   const int *conn=_nodal_connec->getConstPointer();
6267   const int *connI=_nodal_connec_index->getConstPointer();
6268   const double *coo=_coords->getConstPointer();
6269   double tmp[12];
6270   for(int i=0;i<nbOfCells;i++,pt++)
6271     {
6272       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6273       switch(t)
6274         {
6275           case INTERP_KERNEL::NORM_QUAD4:
6276             {
6277               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6278               *pt=INTERP_KERNEL::quadWarp(tmp);
6279               break;
6280             }
6281         default:
6282           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6283         }
6284       conn+=connI[i+1]-connI[i];
6285     }
6286   ret->setName("Warp");
6287   ret->synchronizeTimeWithSupport();
6288   return ret.retn();
6289 }
6290
6291
6292 /*!
6293  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6294  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6295  * treated: INTERP_KERNEL::NORM_QUAD4.
6296  * For a cell of other type an exception is thrown.
6297  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6298  *          cells and one time, lying on \a this mesh. The caller is to delete this
6299  *          field using decrRef() as it is no more needed. 
6300  *  \throw If the coordinates array is not set.
6301  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6302  *  \throw If the connectivity data array has more than one component.
6303  *  \throw If the connectivity data array has a named component.
6304  *  \throw If the connectivity index data array has more than one component.
6305  *  \throw If the connectivity index data array has a named component.
6306  *  \throw If \a this->getMeshDimension() != 2.
6307  *  \throw If \a this->getSpaceDimension() != 3.
6308  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6309  */
6310 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6311 {
6312   checkCoherency();
6313   int spaceDim=getSpaceDimension();
6314   int meshDim=getMeshDimension();
6315   if(spaceDim!=3)
6316     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6317   if(meshDim!=2)
6318     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6319   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6320   ret->setMesh(this);
6321   int nbOfCells=getNumberOfCells();
6322   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6323   arr->alloc(nbOfCells,1);
6324   double *pt=arr->getPointer();
6325   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6326   const int *conn=_nodal_connec->getConstPointer();
6327   const int *connI=_nodal_connec_index->getConstPointer();
6328   const double *coo=_coords->getConstPointer();
6329   double tmp[12];
6330   for(int i=0;i<nbOfCells;i++,pt++)
6331     {
6332       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6333       switch(t)
6334         {
6335           case INTERP_KERNEL::NORM_QUAD4:
6336             {
6337               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6338               *pt=INTERP_KERNEL::quadSkew(tmp);
6339               break;
6340             }
6341         default:
6342           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6343         }
6344       conn+=connI[i+1]-connI[i];
6345     }
6346   ret->setName("Skew");
6347   ret->synchronizeTimeWithSupport();
6348   return ret.retn();
6349 }
6350
6351 /*!
6352  * This method aggregate the bbox of each cell and put it into bbox parameter.
6353  * 
6354  * \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)
6355  *                         For all other cases this input parameter is ignored.
6356  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6357  * 
6358  * \throw If \a this is not fully set (coordinates and connectivity).
6359  * \throw If a cell in \a this has no valid nodeId.
6360  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6361  */
6362 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6363 {
6364   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6365   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.
6366     return getBoundingBoxForBBTreeFast();
6367   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6368     {
6369       bool presenceOfQuadratic(false);
6370       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6371         {
6372           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6373           if(cm.isQuadratic())
6374             presenceOfQuadratic=true;
6375         }
6376       if(!presenceOfQuadratic)
6377         return getBoundingBoxForBBTreeFast();
6378       if(mDim==2 && sDim==2)
6379         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6380       else
6381         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6382     }
6383   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) !");
6384 }
6385
6386 /*!
6387  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6388  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6389  * 
6390  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6391  * 
6392  * \throw If \a this is not fully set (coordinates and connectivity).
6393  * \throw If a cell in \a this has no valid nodeId.
6394  */
6395 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6396 {
6397   checkFullyDefined();
6398   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6399   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6400   double *bbox(ret->getPointer());
6401   for(int i=0;i<nbOfCells*spaceDim;i++)
6402     {
6403       bbox[2*i]=std::numeric_limits<double>::max();
6404       bbox[2*i+1]=-std::numeric_limits<double>::max();
6405     }
6406   const double *coordsPtr(_coords->getConstPointer());
6407   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6408   for(int i=0;i<nbOfCells;i++)
6409     {
6410       int offset=connI[i]+1;
6411       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6412       for(int j=0;j<nbOfNodesForCell;j++)
6413         {
6414           int nodeId=conn[offset+j];
6415           if(nodeId>=0 && nodeId<nbOfNodes)
6416             {
6417               for(int k=0;k<spaceDim;k++)
6418                 {
6419                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6420                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6421                 }
6422               kk++;
6423             }
6424         }
6425       if(kk==0)
6426         {
6427           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6428           throw INTERP_KERNEL::Exception(oss.str().c_str());
6429         }
6430     }
6431   return ret.retn();
6432 }
6433
6434 /*!
6435  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6436  * useful for 2D meshes having quadratic cells
6437  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6438  * the two extremities of the arc of circle).
6439  * 
6440  * \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)
6441  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6442  * \throw If \a this is not fully defined.
6443  * \throw If \a this is not a mesh with meshDimension equal to 2.
6444  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6445  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6446  */
6447 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6448 {
6449   checkFullyDefined();
6450   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6451   if(spaceDim!=2 || mDim!=2)
6452     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!");
6453   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6454   double *bbox(ret->getPointer());
6455   const double *coords(_coords->getConstPointer());
6456   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6457   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6458     {
6459       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6460       int sz(connI[1]-connI[0]-1);
6461       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6462       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6463       INTERP_KERNEL::QuadraticPolygon *pol(0);
6464       for(int j=0;j<sz;j++)
6465         {
6466           int nodeId(conn[*connI+1+j]);
6467           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6468         }
6469       if(!cm.isQuadratic())
6470         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6471       else
6472         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6473       INTERP_KERNEL::Bounds b; pol->fillBounds(b); delete pol;
6474       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6475     }
6476   return ret.retn();
6477 }
6478
6479 /*!
6480  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6481  * useful for 2D meshes having quadratic cells
6482  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6483  * the two extremities of the arc of circle).
6484  * 
6485  * \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)
6486  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6487  * \throw If \a this is not fully defined.
6488  * \throw If \a this is not a mesh with meshDimension equal to 1.
6489  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6490  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6491  */
6492 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6493 {
6494   checkFullyDefined();
6495   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6496   if(spaceDim!=2 || mDim!=1)
6497     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!");
6498   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6499   double *bbox(ret->getPointer());
6500   const double *coords(_coords->getConstPointer());
6501   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6502   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6503     {
6504       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6505       int sz(connI[1]-connI[0]-1);
6506       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6507       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6508       INTERP_KERNEL::Edge *edge(0);
6509       for(int j=0;j<sz;j++)
6510         {
6511           int nodeId(conn[*connI+1+j]);
6512           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6513         }
6514       if(!cm.isQuadratic())
6515         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6516       else
6517         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6518       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6519       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6520     }
6521   return ret.retn();
6522 }
6523
6524 /// @cond INTERNAL
6525
6526 namespace ParaMEDMEMImpl
6527 {
6528   class ConnReader
6529   {
6530   public:
6531     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6532     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6533   private:
6534     const int *_conn;
6535     int _val;
6536   };
6537
6538   class ConnReader2
6539   {
6540   public:
6541     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6542     bool operator() (const int& pos) { return _conn[pos]==_val; }
6543   private:
6544     const int *_conn;
6545     int _val;
6546   };
6547 }
6548
6549 /// @endcond
6550
6551 /*!
6552  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6553  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6554  * \a this is composed in cell types.
6555  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6556  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6557  * This parameter is kept only for compatibility with other methode listed above.
6558  */
6559 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6560 {
6561   checkConnectivityFullyDefined();
6562   const int *conn=_nodal_connec->getConstPointer();
6563   const int *connI=_nodal_connec_index->getConstPointer();
6564   const int *work=connI;
6565   int nbOfCells=getNumberOfCells();
6566   std::size_t n=getAllGeoTypes().size();
6567   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6568   std::set<INTERP_KERNEL::NormalizedCellType> types;
6569   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6570     {
6571       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6572       if(types.find(typ)!=types.end())
6573         {
6574           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6575           oss << " is not contiguous !";
6576           throw INTERP_KERNEL::Exception(oss.str().c_str());
6577         }
6578       types.insert(typ);
6579       ret[3*i]=typ;
6580       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6581       ret[3*i+1]=(int)std::distance(work,work2);
6582       work=work2;
6583     }
6584   return ret;
6585 }
6586
6587 /*!
6588  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6589  * only for types cell, type node is not managed.
6590  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6591  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6592  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6593  * If 2 or more same geometric type is in \a code and exception is thrown too.
6594  *
6595  * This method firstly checks
6596  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6597  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6598  * an exception is thrown too.
6599  * 
6600  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6601  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6602  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6603  */
6604 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6605 {
6606   if(code.empty())
6607     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6608   std::size_t sz=code.size();
6609   std::size_t n=sz/3;
6610   if(sz%3!=0)
6611     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6612   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6613   int nb=0;
6614   bool isNoPflUsed=true;
6615   for(std::size_t i=0;i<n;i++)
6616     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6617       {
6618         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6619         nb+=code[3*i+1];
6620         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6621           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6622         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6623       }
6624   if(types.size()!=n)
6625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6626   if(isNoPflUsed)
6627     {
6628       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6629         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6630       if(types.size()==_types.size())
6631         return 0;
6632     }
6633   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6634   ret->alloc(nb,1);
6635   int *retPtr=ret->getPointer();
6636   const int *connI=_nodal_connec_index->getConstPointer();
6637   const int *conn=_nodal_connec->getConstPointer();
6638   int nbOfCells=getNumberOfCells();
6639   const int *i=connI;
6640   int kk=0;
6641   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6642     {
6643       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6644       int offset=(int)std::distance(connI,i);
6645       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6646       int nbOfCellsOfCurType=(int)std::distance(i,j);
6647       if(code[3*kk+2]==-1)
6648         for(int k=0;k<nbOfCellsOfCurType;k++)
6649           *retPtr++=k+offset;
6650       else
6651         {
6652           int idInIdsPerType=code[3*kk+2];
6653           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6654             {
6655               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6656               if(zePfl)
6657                 {
6658                   zePfl->checkAllocated();
6659                   if(zePfl->getNumberOfComponents()==1)
6660                     {
6661                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6662                         {
6663                           if(*k>=0 && *k<nbOfCellsOfCurType)
6664                             *retPtr=(*k)+offset;
6665                           else
6666                             {
6667                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6668                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6669                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6670                             }
6671                         }
6672                     }
6673                   else
6674                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6675                 }
6676               else
6677                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6678             }
6679           else
6680             {
6681               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6682               oss << " should be in [0," << idsPerType.size() << ") !";
6683               throw INTERP_KERNEL::Exception(oss.str().c_str());
6684             }
6685         }
6686       i=j;
6687     }
6688   return ret.retn();
6689 }
6690
6691 /*!
6692  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6693  * 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.
6694  * 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.
6695  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6696  * 
6697  * \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.
6698  * \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,
6699  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6700  * \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.
6701  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6702  * \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
6703  */
6704 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6705 {
6706   if(!profile)
6707     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6708   if(profile->getNumberOfComponents()!=1)
6709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6710   checkConnectivityFullyDefined();
6711   const int *conn=_nodal_connec->getConstPointer();
6712   const int *connI=_nodal_connec_index->getConstPointer();
6713   int nbOfCells=getNumberOfCells();
6714   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6715   std::vector<int> typeRangeVals(1);
6716   for(const int *i=connI;i!=connI+nbOfCells;)
6717     {
6718       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6719       if(std::find(types.begin(),types.end(),curType)!=types.end())
6720         {
6721           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6722         }
6723       types.push_back(curType);
6724       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6725       typeRangeVals.push_back((int)std::distance(connI,i));
6726     }
6727   //
6728   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6729   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6730   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6731   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6732   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6733   //
6734   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6735   code.resize(3*nbOfCastsFinal);
6736   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6737   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6738   for(int i=0;i<nbOfCastsFinal;i++)
6739     {
6740       int castId=castsPresent->getIJ(i,0);
6741       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6742       idsInPflPerType2.push_back(tmp3);
6743       code[3*i]=(int)types[castId];
6744       code[3*i+1]=tmp3->getNumberOfTuples();
6745       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6746       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6747         {
6748           tmp4->copyStringInfoFrom(*profile);
6749           idsPerType2.push_back(tmp4);
6750           code[3*i+2]=(int)idsPerType2.size()-1;
6751         }
6752       else
6753         {
6754           code[3*i+2]=-1;
6755         }
6756     }
6757   std::size_t sz2=idsInPflPerType2.size();
6758   idsInPflPerType.resize(sz2);
6759   for(std::size_t i=0;i<sz2;i++)
6760     {
6761       DataArrayInt *locDa=idsInPflPerType2[i];
6762       locDa->incrRef();
6763       idsInPflPerType[i]=locDa;
6764     }
6765   std::size_t sz=idsPerType2.size();
6766   idsPerType.resize(sz);
6767   for(std::size_t i=0;i<sz;i++)
6768     {
6769       DataArrayInt *locDa=idsPerType2[i];
6770       locDa->incrRef();
6771       idsPerType[i]=locDa;
6772     }
6773 }
6774
6775 /*!
6776  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6777  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6778  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6779  * 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.
6780  */
6781 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6782 {
6783   checkFullyDefined();
6784   nM1LevMesh->checkFullyDefined();
6785   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6786     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6787   if(_coords!=nM1LevMesh->getCoords())
6788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6789   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6790   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6791   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6792   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6793   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6794   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6795   tmp->setConnectivity(tmp0,tmp1);
6796   tmp->renumberCells(ret0->getConstPointer(),false);
6797   revDesc=tmp->getNodalConnectivity();
6798   revDescIndx=tmp->getNodalConnectivityIndex();
6799   DataArrayInt *ret=0;
6800   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6801     {
6802       int tmp2;
6803       ret->getMaxValue(tmp2);
6804       ret->decrRef();
6805       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6806       throw INTERP_KERNEL::Exception(oss.str().c_str());
6807     }
6808   nM1LevMeshIds=ret;
6809   //
6810   revDesc->incrRef();
6811   revDescIndx->incrRef();
6812   ret1->incrRef();
6813   ret0->incrRef();
6814   meshnM1Old2New=ret0;
6815   return ret1;
6816 }
6817
6818 /*!
6819  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6820  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6821  * in "Old to New" mode.
6822  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6823  *          this array using decrRef() as it is no more needed.
6824  *  \throw If the nodal connectivity of cells is not defined.
6825  */
6826 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6827 {
6828   checkConnectivityFullyDefined();
6829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6830   renumberCells(ret->getConstPointer(),false);
6831   return ret.retn();
6832 }
6833
6834 /*!
6835  * This methods checks that cells are sorted by their types.
6836  * This method makes asumption (no check) that connectivity is correctly set before calling.
6837  */
6838 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6839 {
6840   checkFullyDefined();
6841   const int *conn=_nodal_connec->getConstPointer();
6842   const int *connI=_nodal_connec_index->getConstPointer();
6843   int nbOfCells=getNumberOfCells();
6844   std::set<INTERP_KERNEL::NormalizedCellType> types;
6845   for(const int *i=connI;i!=connI+nbOfCells;)
6846     {
6847       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6848       if(types.find(curType)!=types.end())
6849         return false;
6850       types.insert(curType);
6851       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6852     }
6853   return true;
6854 }
6855
6856 /*!
6857  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6858  * The geometric type order is specified by MED file.
6859  * 
6860  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6861  */
6862 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6863 {
6864   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6865 }
6866
6867 /*!
6868  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6869  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6870  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6871  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6872  */
6873 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6874 {
6875   checkFullyDefined();
6876   const int *conn=_nodal_connec->getConstPointer();
6877   const int *connI=_nodal_connec_index->getConstPointer();
6878   int nbOfCells=getNumberOfCells();
6879   if(nbOfCells==0)
6880     return true;
6881   int lastPos=-1;
6882   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6883   for(const int *i=connI;i!=connI+nbOfCells;)
6884     {
6885       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6886       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6887       if(isTypeExists!=orderEnd)
6888         {
6889           int pos=(int)std::distance(orderBg,isTypeExists);
6890           if(pos<=lastPos)
6891             return false;
6892           lastPos=pos;
6893           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6894         }
6895       else
6896         {
6897           if(sg.find(curType)==sg.end())
6898             {
6899               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6900               sg.insert(curType);
6901             }
6902           else
6903             return false;
6904         }
6905     }
6906   return true;
6907 }
6908
6909 /*!
6910  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6911  * 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
6912  * 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'.
6913  */
6914 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6915 {
6916   checkConnectivityFullyDefined();
6917   int nbOfCells=getNumberOfCells();
6918   const int *conn=_nodal_connec->getConstPointer();
6919   const int *connI=_nodal_connec_index->getConstPointer();
6920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6921   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6922   tmpa->alloc(nbOfCells,1);
6923   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6924   tmpb->fillWithZero();
6925   int *tmp=tmpa->getPointer();
6926   int *tmp2=tmpb->getPointer();
6927   for(const int *i=connI;i!=connI+nbOfCells;i++)
6928     {
6929       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6930       if(where!=orderEnd)
6931         {
6932           int pos=(int)std::distance(orderBg,where);
6933           tmp2[pos]++;
6934           tmp[std::distance(connI,i)]=pos;
6935         }
6936       else
6937         {
6938           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6939           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6940           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6941           throw INTERP_KERNEL::Exception(oss.str().c_str());
6942         }
6943     }
6944   nbPerType=tmpb.retn();
6945   return tmpa.retn();
6946 }
6947
6948 /*!
6949  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6950  *
6951  * \return a new object containing the old to new correspondance.
6952  *
6953  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6954  */
6955 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6956 {
6957   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6958 }
6959
6960 /*!
6961  * 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.
6962  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6963  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6964  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6965  */
6966 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6967 {
6968   DataArrayInt *nbPerType=0;
6969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6970   nbPerType->decrRef();
6971   return tmpa->buildPermArrPerLevel();
6972 }
6973
6974 /*!
6975  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6976  * The number of cells remains unchanged after the call of this method.
6977  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6978  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6979  *
6980  * \return the array giving the correspondance old to new.
6981  */
6982 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6983 {
6984   checkFullyDefined();
6985   computeTypes();
6986   const int *conn=_nodal_connec->getConstPointer();
6987   const int *connI=_nodal_connec_index->getConstPointer();
6988   int nbOfCells=getNumberOfCells();
6989   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6990   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6991     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6992       {
6993         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6994         types.push_back(curType);
6995         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6996       }
6997   DataArrayInt *ret=DataArrayInt::New();
6998   ret->alloc(nbOfCells,1);
6999   int *retPtr=ret->getPointer();
7000   std::fill(retPtr,retPtr+nbOfCells,-1);
7001   int newCellId=0;
7002   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7003     {
7004       for(const int *i=connI;i!=connI+nbOfCells;i++)
7005         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7006           retPtr[std::distance(connI,i)]=newCellId++;
7007     }
7008   renumberCells(retPtr,false);
7009   return ret;
7010 }
7011
7012 /*!
7013  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7014  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7015  * This method makes asumption that connectivity is correctly set before calling.
7016  */
7017 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7018 {
7019   checkConnectivityFullyDefined();
7020   const int *conn=_nodal_connec->getConstPointer();
7021   const int *connI=_nodal_connec_index->getConstPointer();
7022   int nbOfCells=getNumberOfCells();
7023   std::vector<MEDCouplingUMesh *> ret;
7024   for(const int *i=connI;i!=connI+nbOfCells;)
7025     {
7026       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7027       int beginCellId=(int)std::distance(connI,i);
7028       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7029       int endCellId=(int)std::distance(connI,i);
7030       int sz=endCellId-beginCellId;
7031       int *cells=new int[sz];
7032       for(int j=0;j<sz;j++)
7033         cells[j]=beginCellId+j;
7034       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7035       delete [] cells;
7036       ret.push_back(m);
7037     }
7038   return ret;
7039 }
7040
7041 /*!
7042  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7043  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7044  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7045  *
7046  * \return a newly allocated instance, that the caller must manage.
7047  * \throw If \a this contains more than one geometric type.
7048  * \throw If the nodal connectivity of \a this is not fully defined.
7049  * \throw If the internal data is not coherent.
7050  */
7051 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7052 {
7053   checkConnectivityFullyDefined();
7054     if(_types.size()!=1)
7055     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7056   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7057   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7058   ret->setCoords(getCoords());
7059   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7060   if(retC)
7061     {
7062       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7063       retC->setNodalConnectivity(c);
7064     }
7065   else
7066     {
7067       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7068       if(!retD)
7069         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7070       DataArrayInt *c=0,*ci=0;
7071       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7072       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7073       retD->setNodalConnectivity(cs,cis);
7074     }
7075   return ret.retn();
7076 }
7077
7078 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7079 {
7080   checkConnectivityFullyDefined();
7081     if(_types.size()!=1)
7082     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7083   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7084   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7085   if(cm.isDynamic())
7086     {
7087       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7088       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7089       throw INTERP_KERNEL::Exception(oss.str().c_str());
7090     }
7091   int nbCells=getNumberOfCells();
7092   int typi=(int)typ;
7093   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7094   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7095   int *outPtr=connOut->getPointer();
7096   const int *conn=_nodal_connec->begin();
7097   const int *connI=_nodal_connec_index->begin();
7098   nbNodesPerCell++;
7099   for(int i=0;i<nbCells;i++,connI++)
7100     {
7101       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7102         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7103       else
7104         {
7105           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 << ") !";
7106           throw INTERP_KERNEL::Exception(oss.str().c_str());
7107         }
7108     }
7109   return connOut.retn();
7110 }
7111
7112 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7113 {
7114   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7115   checkConnectivityFullyDefined();
7116   if(_types.size()!=1)
7117     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7118   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7119   if(lgth<nbCells)
7120     throw INTERP_KERNEL::Exception(msg0);
7121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7122   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7123   int *cp(c->getPointer()),*cip(ci->getPointer());
7124   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7125   cip[0]=0;
7126   for(int i=0;i<nbCells;i++,cip++,incip++)
7127     {
7128       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7129       int delta(stop-strt);
7130       if(delta>=1)
7131         {
7132           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7133             cp=std::copy(incp+strt,incp+stop,cp);
7134           else
7135             throw INTERP_KERNEL::Exception(msg0);
7136         }
7137       else
7138         throw INTERP_KERNEL::Exception(msg0);
7139       cip[1]=cip[0]+delta;
7140     }
7141   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7142 }
7143
7144 /*!
7145  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7146  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7147  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7148  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7149  * are not used here to avoid the build of big permutation array.
7150  *
7151  * \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
7152  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7153  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7154  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7155  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7156  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7157  * \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
7158  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7159  */
7160 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7161                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7162                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7163 {
7164   std::vector<const MEDCouplingUMesh *> ms2;
7165   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7166     if(*it)
7167       {
7168         (*it)->checkConnectivityFullyDefined();
7169         ms2.push_back(*it);
7170       }
7171   if(ms2.empty())
7172     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7173   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7174   int meshDim=ms2[0]->getMeshDimension();
7175   std::vector<const MEDCouplingUMesh *> m1ssm;
7176   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7177   //
7178   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7179   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7180   int fake=0,rk=0;
7181   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7182   ret1->alloc(0,1); ret2->alloc(0,1);
7183   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7184     {
7185       if(meshDim!=(*it)->getMeshDimension())
7186         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7187       if(refCoo!=(*it)->getCoords())
7188         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7189       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7190       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7191       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7192       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7193         {
7194           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7195           m1ssmSingleAuto.push_back(singleCell);
7196           m1ssmSingle.push_back(singleCell);
7197           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7198         }
7199     }
7200   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7202   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7203   for(std::size_t i=0;i<m1ssm.size();i++)
7204     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7205   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7206   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7207   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7208   return ret0.retn();
7209 }
7210
7211 /*!
7212  * This method returns a newly created DataArrayInt instance.
7213  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7214  */
7215 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7216 {
7217   checkFullyDefined();
7218   const int *conn=_nodal_connec->getConstPointer();
7219   const int *connIndex=_nodal_connec_index->getConstPointer();
7220   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7221   for(const int *w=begin;w!=end;w++)
7222     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7223       ret->pushBackSilent(*w);
7224   return ret.retn();
7225 }
7226
7227 /*!
7228  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7229  * are in [0:getNumberOfCells())
7230  */
7231 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7232 {
7233   checkFullyDefined();
7234   const int *conn=_nodal_connec->getConstPointer();
7235   const int *connI=_nodal_connec_index->getConstPointer();
7236   int nbOfCells=getNumberOfCells();
7237   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7238   int *tmp=new int[nbOfCells];
7239   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7240     {
7241       int j=0;
7242       for(const int *i=connI;i!=connI+nbOfCells;i++)
7243         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7244           tmp[std::distance(connI,i)]=j++;
7245     }
7246   DataArrayInt *ret=DataArrayInt::New();
7247   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7248   ret->copyStringInfoFrom(*da);
7249   int *retPtr=ret->getPointer();
7250   const int *daPtr=da->getConstPointer();
7251   int nbOfElems=da->getNbOfElems();
7252   for(int k=0;k<nbOfElems;k++)
7253     retPtr[k]=tmp[daPtr[k]];
7254   delete [] tmp;
7255   return ret;
7256 }
7257
7258 /*!
7259  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7260  * This method \b works \b for mesh sorted by type.
7261  * cells whose ids is in 'idsPerGeoType' array.
7262  * This method conserves coords and name of mesh.
7263  */
7264 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7265 {
7266   std::vector<int> code=getDistributionOfTypes();
7267   std::size_t nOfTypesInThis=code.size()/3;
7268   int sz=0,szOfType=0;
7269   for(std::size_t i=0;i<nOfTypesInThis;i++)
7270     {
7271       if(code[3*i]!=type)
7272         sz+=code[3*i+1];
7273       else
7274         szOfType=code[3*i+1];
7275     }
7276   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7277     if(*work<0 || *work>=szOfType)
7278       {
7279         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7280         oss << ". It should be in [0," << szOfType << ") !";
7281         throw INTERP_KERNEL::Exception(oss.str().c_str());
7282       }
7283   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7284   int *idsPtr=idsTokeep->getPointer();
7285   int offset=0;
7286   for(std::size_t i=0;i<nOfTypesInThis;i++)
7287     {
7288       if(code[3*i]!=type)
7289         for(int j=0;j<code[3*i+1];j++)
7290           *idsPtr++=offset+j;
7291       else
7292         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7293       offset+=code[3*i+1];
7294     }
7295   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7296   ret->copyTinyInfoFrom(this);
7297   return ret.retn();
7298 }
7299
7300 /*!
7301  * This method returns a vector of size 'this->getNumberOfCells()'.
7302  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7303  */
7304 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7305 {
7306   int ncell=getNumberOfCells();
7307   std::vector<bool> ret(ncell);
7308   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7309   const int *c=getNodalConnectivity()->getConstPointer();
7310   for(int i=0;i<ncell;i++)
7311     {
7312       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7313       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7314       ret[i]=cm.isQuadratic();
7315     }
7316   return ret;
7317 }
7318
7319 /*!
7320  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7321  */
7322 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7323 {
7324   if(other->getType()!=UNSTRUCTURED)
7325     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7326   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7327   return MergeUMeshes(this,otherC);
7328 }
7329
7330 /*!
7331  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7332  * computed by averaging coordinates of cell nodes, so this method is not a right
7333  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7334  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7335  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7336  *          components. The caller is to delete this array using decrRef() as it is
7337  *          no more needed.
7338  *  \throw If the coordinates array is not set.
7339  *  \throw If the nodal connectivity of cells is not defined.
7340  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7341  */
7342 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7343 {
7344   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7345   int spaceDim=getSpaceDimension();
7346   int nbOfCells=getNumberOfCells();
7347   ret->alloc(nbOfCells,spaceDim);
7348   ret->copyStringInfoFrom(*getCoords());
7349   double *ptToFill=ret->getPointer();
7350   const int *nodal=_nodal_connec->getConstPointer();
7351   const int *nodalI=_nodal_connec_index->getConstPointer();
7352   const double *coor=_coords->getConstPointer();
7353   for(int i=0;i<nbOfCells;i++)
7354     {
7355       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7356       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7357       ptToFill+=spaceDim;
7358     }
7359   return ret.retn();
7360 }
7361
7362 /*!
7363  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7364  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7365  * 
7366  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7367  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7368  * 
7369  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7370  * \throw If \a this is not fully defined (coordinates and connectivity)
7371  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7372  */
7373 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7374 {
7375   checkFullyDefined();
7376   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7377   int spaceDim=getSpaceDimension();
7378   int nbOfCells=getNumberOfCells();
7379   int nbOfNodes=getNumberOfNodes();
7380   ret->alloc(nbOfCells,spaceDim);
7381   double *ptToFill=ret->getPointer();
7382   const int *nodal=_nodal_connec->getConstPointer();
7383   const int *nodalI=_nodal_connec_index->getConstPointer();
7384   const double *coor=_coords->getConstPointer();
7385   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7386     {
7387       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7388       std::fill(ptToFill,ptToFill+spaceDim,0.);
7389       if(type!=INTERP_KERNEL::NORM_POLYHED)
7390         {
7391           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7392             {
7393               if(*conn>=0 && *conn<nbOfNodes)
7394                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7395               else
7396                 {
7397                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7398                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7399                 }
7400             }
7401           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7402           if(nbOfNodesInCell>0)
7403             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7404           else
7405             {
7406               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7407               throw INTERP_KERNEL::Exception(oss.str().c_str());
7408             }
7409         }
7410       else
7411         {
7412           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7413           s.erase(-1);
7414           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7415             {
7416               if(*it>=0 && *it<nbOfNodes)
7417                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7418               else
7419                 {
7420                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7421                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7422                 }
7423             }
7424           if(!s.empty())
7425             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7426           else
7427             {
7428               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7429               throw INTERP_KERNEL::Exception(oss.str().c_str());
7430             }
7431         }
7432     }
7433   return ret.retn();
7434 }
7435
7436 /*!
7437  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7438  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7439  * are specified via an array of cell ids. 
7440  *  \warning Validity of the specified cell ids is not checked! 
7441  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7442  *  \param [in] begin - an array of cell ids of interest.
7443  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7444  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7445  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7446  *          caller is to delete this array using decrRef() as it is no more needed. 
7447  *  \throw If the coordinates array is not set.
7448  *  \throw If the nodal connectivity of cells is not defined.
7449  *
7450  *  \if ENABLE_EXAMPLES
7451  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7452  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7453  *  \endif
7454  */
7455 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7456 {
7457   DataArrayDouble *ret=DataArrayDouble::New();
7458   int spaceDim=getSpaceDimension();
7459   int nbOfTuple=(int)std::distance(begin,end);
7460   ret->alloc(nbOfTuple,spaceDim);
7461   double *ptToFill=ret->getPointer();
7462   double *tmp=new double[spaceDim];
7463   const int *nodal=_nodal_connec->getConstPointer();
7464   const int *nodalI=_nodal_connec_index->getConstPointer();
7465   const double *coor=_coords->getConstPointer();
7466   for(const int *w=begin;w!=end;w++)
7467     {
7468       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7469       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7470       ptToFill+=spaceDim;
7471     }
7472   delete [] tmp;
7473   return ret;
7474 }
7475
7476 /*!
7477  * 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".
7478  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7479  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7480  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7481  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7482  * 
7483  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7484  * \throw If spaceDim!=3 or meshDim!=2.
7485  * \throw If connectivity of \a this is invalid.
7486  * \throw If connectivity of a cell in \a this points to an invalid node.
7487  */
7488 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7489 {
7490   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7491   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7492   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7493     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7494   ret->alloc(nbOfCells,4);
7495   double *retPtr(ret->getPointer());
7496   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7497   const double *coor(_coords->begin());
7498   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7499     {
7500       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7501       if(nodalI[1]-nodalI[0]>=3)
7502         {
7503           for(int j=0;j<3;j++)
7504             {
7505               int nodeId(nodal[nodalI[0]+1+j]);
7506               if(nodeId>=0 && nodeId<nbOfNodes)
7507                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7508               else
7509                 {
7510                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7511                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7512                 }
7513             }
7514         }
7515       else
7516         {
7517           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7518           throw INTERP_KERNEL::Exception(oss.str().c_str());
7519         }
7520       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7521       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7522     }
7523   return ret.retn();
7524 }
7525
7526 /*!
7527  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7528  * 
7529  */
7530 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7531 {
7532   if(!da)
7533     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7534   da->checkAllocated();
7535   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7536   ret->setCoords(da);
7537   int nbOfTuples=da->getNumberOfTuples();
7538   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7539   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7540   c->alloc(2*nbOfTuples,1);
7541   cI->alloc(nbOfTuples+1,1);
7542   int *cp=c->getPointer();
7543   int *cip=cI->getPointer();
7544   *cip++=0;
7545   for(int i=0;i<nbOfTuples;i++)
7546     {
7547       *cp++=INTERP_KERNEL::NORM_POINT1;
7548       *cp++=i;
7549       *cip++=2*(i+1);
7550     }
7551   ret->setConnectivity(c,cI,true);
7552   return ret.retn();
7553 }
7554 /*!
7555  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7556  * Cells and nodes of
7557  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7558  *  \param [in] mesh1 - the first mesh.
7559  *  \param [in] mesh2 - the second mesh.
7560  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7561  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7562  *          is no more needed.
7563  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7564  *  \throw If the coordinates array is not set in none of the meshes.
7565  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7566  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7567  */
7568 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7569 {
7570   std::vector<const MEDCouplingUMesh *> tmp(2);
7571   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7572   return MergeUMeshes(tmp);
7573 }
7574
7575 /*!
7576  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7577  * Cells and nodes of
7578  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7579  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7580  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7581  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7582  *          is no more needed.
7583  *  \throw If \a a.size() == 0.
7584  *  \throw If \a a[ *i* ] == NULL.
7585  *  \throw If the coordinates array is not set in none of the meshes.
7586  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7587  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7588 */
7589 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7590 {
7591   std::size_t sz=a.size();
7592   if(sz==0)
7593     return MergeUMeshesLL(a);
7594   for(std::size_t ii=0;ii<sz;ii++)
7595     if(!a[ii])
7596       {
7597         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7598         throw INTERP_KERNEL::Exception(oss.str().c_str());
7599       }
7600   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7601   std::vector< const MEDCouplingUMesh * > aa(sz);
7602   int spaceDim=-3;
7603   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7604     {
7605       const MEDCouplingUMesh *cur=a[i];
7606       const DataArrayDouble *coo=cur->getCoords();
7607       if(coo)
7608         spaceDim=coo->getNumberOfComponents();
7609     }
7610   if(spaceDim==-3)
7611     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7612   for(std::size_t i=0;i<sz;i++)
7613     {
7614       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7615       aa[i]=bb[i];
7616     }
7617   return MergeUMeshesLL(aa);
7618 }
7619
7620 /// @cond INTERNAL
7621
7622 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7623 {
7624   if(a.empty())
7625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7626   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7627   int meshDim=(*it)->getMeshDimension();
7628   int nbOfCells=(*it)->getNumberOfCells();
7629   int meshLgth=(*it++)->getMeshLength();
7630   for(;it!=a.end();it++)
7631     {
7632       if(meshDim!=(*it)->getMeshDimension())
7633         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7634       nbOfCells+=(*it)->getNumberOfCells();
7635       meshLgth+=(*it)->getMeshLength();
7636     }
7637   std::vector<const MEDCouplingPointSet *> aps(a.size());
7638   std::copy(a.begin(),a.end(),aps.begin());
7639   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7640   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7641   ret->setCoords(pts);
7642   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7643   c->alloc(meshLgth,1);
7644   int *cPtr=c->getPointer();
7645   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7646   cI->alloc(nbOfCells+1,1);
7647   int *cIPtr=cI->getPointer();
7648   *cIPtr++=0;
7649   int offset=0;
7650   int offset2=0;
7651   for(it=a.begin();it!=a.end();it++)
7652     {
7653       int curNbOfCell=(*it)->getNumberOfCells();
7654       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7655       const int *curC=(*it)->_nodal_connec->getConstPointer();
7656       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7657       for(int j=0;j<curNbOfCell;j++)
7658         {
7659           const int *src=curC+curCI[j];
7660           *cPtr++=*src++;
7661           for(;src!=curC+curCI[j+1];src++,cPtr++)
7662             {
7663               if(*src!=-1)
7664                 *cPtr=*src+offset2;
7665               else
7666                 *cPtr=-1;
7667             }
7668         }
7669       offset+=curCI[curNbOfCell];
7670       offset2+=(*it)->getNumberOfNodes();
7671     }
7672   //
7673   ret->setConnectivity(c,cI,true);
7674   return ret.retn();
7675 }
7676
7677 /// @endcond
7678
7679 /*!
7680  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7681  * dimension and sharing the node coordinates array.
7682  * All cells of the first mesh precede all cells of the second mesh
7683  * within the result mesh. 
7684  *  \param [in] mesh1 - the first mesh.
7685  *  \param [in] mesh2 - the second mesh.
7686  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7687  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7688  *          is no more needed.
7689  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7690  *  \throw If the meshes do not share the node coordinates array.
7691  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7692  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7693  */
7694 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7695 {
7696   std::vector<const MEDCouplingUMesh *> tmp(2);
7697   tmp[0]=mesh1; tmp[1]=mesh2;
7698   return MergeUMeshesOnSameCoords(tmp);
7699 }
7700
7701 /*!
7702  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7703  * dimension and sharing the node coordinates array.
7704  * All cells of the *i*-th mesh precede all cells of the
7705  * (*i*+1)-th mesh within the result mesh.
7706  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7707  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7708  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7709  *          is no more needed.
7710  *  \throw If \a a.size() == 0.
7711  *  \throw If \a a[ *i* ] == NULL.
7712  *  \throw If the meshes do not share the node coordinates array.
7713  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7714  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7715  */
7716 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7717 {
7718   if(meshes.empty())
7719     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7720   for(std::size_t ii=0;ii<meshes.size();ii++)
7721     if(!meshes[ii])
7722       {
7723         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7724         throw INTERP_KERNEL::Exception(oss.str().c_str());
7725       }
7726   const DataArrayDouble *coords=meshes.front()->getCoords();
7727   int meshDim=meshes.front()->getMeshDimension();
7728   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7729   int meshLgth=0;
7730   int meshIndexLgth=0;
7731   for(;iter!=meshes.end();iter++)
7732     {
7733       if(coords!=(*iter)->getCoords())
7734         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7735       if(meshDim!=(*iter)->getMeshDimension())
7736         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7737       meshLgth+=(*iter)->getMeshLength();
7738       meshIndexLgth+=(*iter)->getNumberOfCells();
7739     }
7740   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7741   nodal->alloc(meshLgth,1);
7742   int *nodalPtr=nodal->getPointer();
7743   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7744   nodalIndex->alloc(meshIndexLgth+1,1);
7745   int *nodalIndexPtr=nodalIndex->getPointer();
7746   int offset=0;
7747   for(iter=meshes.begin();iter!=meshes.end();iter++)
7748     {
7749       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7750       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7751       int nbOfCells=(*iter)->getNumberOfCells();
7752       int meshLgth2=(*iter)->getMeshLength();
7753       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7754       if(iter!=meshes.begin())
7755         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7756       else
7757         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7758       offset+=meshLgth2;
7759     }
7760   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7761   ret->setName("merge");
7762   ret->setMeshDimension(meshDim);
7763   ret->setConnectivity(nodal,nodalIndex,true);
7764   ret->setCoords(coords);
7765   return ret;
7766 }
7767
7768 /*!
7769  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7770  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7771  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7772  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7773  * New" mode are returned for each input mesh.
7774  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7775  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7776  *          valid values [0,1,2], see zipConnectivityTraducer().
7777  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7778  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7779  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7780  *          no more needed.
7781  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7782  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7783  *          is no more needed.
7784  *  \throw If \a meshes.size() == 0.
7785  *  \throw If \a meshes[ *i* ] == NULL.
7786  *  \throw If the meshes do not share the node coordinates array.
7787  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7788  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7789  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7790  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7791  */
7792 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7793 {
7794   //All checks are delegated to MergeUMeshesOnSameCoords
7795   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7796   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7797   corr.resize(meshes.size());
7798   std::size_t nbOfMeshes=meshes.size();
7799   int offset=0;
7800   const int *o2nPtr=o2n->getConstPointer();
7801   for(std::size_t i=0;i<nbOfMeshes;i++)
7802     {
7803       DataArrayInt *tmp=DataArrayInt::New();
7804       int curNbOfCells=meshes[i]->getNumberOfCells();
7805       tmp->alloc(curNbOfCells,1);
7806       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7807       offset+=curNbOfCells;
7808       tmp->setName(meshes[i]->getName());
7809       corr[i]=tmp;
7810     }
7811   return ret.retn();
7812 }
7813
7814 /*!
7815  * Makes all given meshes share the nodal connectivity array. The common connectivity
7816  * array is created by concatenating the connectivity arrays of all given meshes. All
7817  * the given meshes must be of the same space dimension but dimension of cells **can
7818  * differ**. 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  *  \throw If any of \a meshes is NULL.
7823  *  \throw If the coordinates array is not set in any of \a meshes.
7824  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7825  *  \throw If \a meshes are of different space dimension.
7826  */
7827 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7828 {
7829   std::size_t sz=meshes.size();
7830   if(sz==0 || sz==1)
7831     return;
7832   std::vector< const DataArrayDouble * > coords(meshes.size());
7833   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7834   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7835     {
7836       if((*it))
7837         {
7838           (*it)->checkConnectivityFullyDefined();
7839           const DataArrayDouble *coo=(*it)->getCoords();
7840           if(coo)
7841             *it2=coo;
7842           else
7843             {
7844               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7845               oss << " has no coordinate array defined !";
7846               throw INTERP_KERNEL::Exception(oss.str().c_str());
7847             }
7848         }
7849       else
7850         {
7851           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7852           oss << " is null !";
7853           throw INTERP_KERNEL::Exception(oss.str().c_str());
7854         }
7855     }
7856   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7857   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7858   int offset=(*it)->getNumberOfNodes();
7859   (*it++)->setCoords(res);
7860   for(;it!=meshes.end();it++)
7861     {
7862       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7863       (*it)->setCoords(res);
7864       (*it)->shiftNodeNumbersInConn(offset);
7865       offset+=oldNumberOfNodes;
7866     }
7867 }
7868
7869 /*!
7870  * Merges nodes coincident with a given precision within all given meshes that share
7871  * the nodal connectivity array. The given meshes **can be of different** mesh
7872  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7873  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7874  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7875  *  \param [in,out] meshes - a vector of meshes to update.
7876  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7877  *  \throw If any of \a meshes is NULL.
7878  *  \throw If the \a meshes do not share the same node coordinates array.
7879  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7880  */
7881 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7882 {
7883   if(meshes.empty())
7884     return ;
7885   std::set<const DataArrayDouble *> s;
7886   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7887     {
7888       if(*it)
7889         s.insert((*it)->getCoords());
7890       else
7891         {
7892           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 !";
7893           throw INTERP_KERNEL::Exception(oss.str().c_str());
7894         }
7895     }
7896   if(s.size()!=1)
7897     {
7898       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 !";
7899       throw INTERP_KERNEL::Exception(oss.str().c_str());
7900     }
7901   const DataArrayDouble *coo=*(s.begin());
7902   if(!coo)
7903     return;
7904   //
7905   DataArrayInt *comm,*commI;
7906   coo->findCommonTuples(eps,-1,comm,commI);
7907   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7908   int oldNbOfNodes=coo->getNumberOfTuples();
7909   int newNbOfNodes;
7910   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7911   if(oldNbOfNodes==newNbOfNodes)
7912     return ;
7913   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7914   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7915     {
7916       (*it)->renumberNodesInConn(o2n->getConstPointer());
7917       (*it)->setCoords(newCoords);
7918     } 
7919 }
7920
7921 /*!
7922  * 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.
7923  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7924  * \param isQuad specifies the policy of connectivity.
7925  * @ret in/out parameter in which the result will be append
7926  */
7927 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7928 {
7929   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7930   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7931   ret.push_back(cm.getExtrudedType());
7932   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7933   switch(flatType)
7934     {
7935     case INTERP_KERNEL::NORM_POINT1:
7936       {
7937         ret.push_back(connBg[1]);
7938         ret.push_back(connBg[1]+nbOfNodesPerLev);
7939         break;
7940       }
7941     case INTERP_KERNEL::NORM_SEG2:
7942       {
7943         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7944         ret.insert(ret.end(),conn,conn+4);
7945         break;
7946       }
7947     case INTERP_KERNEL::NORM_SEG3:
7948       {
7949         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7950         ret.insert(ret.end(),conn,conn+8);
7951         break;
7952       }
7953     case INTERP_KERNEL::NORM_QUAD4:
7954       {
7955         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7956         ret.insert(ret.end(),conn,conn+8);
7957         break;
7958       }
7959     case INTERP_KERNEL::NORM_TRI3:
7960       {
7961         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7962         ret.insert(ret.end(),conn,conn+6);
7963         break;
7964       }
7965     case INTERP_KERNEL::NORM_TRI6:
7966       {
7967         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,
7968                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7969         ret.insert(ret.end(),conn,conn+15);
7970         break;
7971       }
7972     case INTERP_KERNEL::NORM_QUAD8:
7973       {
7974         int conn[20]={
7975           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7976           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7977           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7978         };
7979         ret.insert(ret.end(),conn,conn+20);
7980         break;
7981       }
7982     case INTERP_KERNEL::NORM_POLYGON:
7983       {
7984         std::back_insert_iterator< std::vector<int> > ii(ret);
7985         std::copy(connBg+1,connEnd,ii);
7986         *ii++=-1;
7987         std::reverse_iterator<const int *> rConnBg(connEnd);
7988         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7989         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7990         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7991         for(std::size_t i=0;i<nbOfRadFaces;i++)
7992           {
7993             *ii++=-1;
7994             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7995             std::copy(conn,conn+4,ii);
7996           }
7997         break;
7998       }
7999     default:
8000       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8001     }
8002 }
8003
8004 /*!
8005  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8006  */
8007 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8008 {
8009   std::size_t i, ip1;
8010   double v[3]={0.,0.,0.};
8011   std::size_t sz=std::distance(begin,end);
8012   if(isQuadratic)
8013     sz/=2;
8014   for(i=0;i<sz;i++)
8015     {
8016       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];
8017       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8018       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8019     }
8020   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8021
8022   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8023   // SEG3 forming a circle):
8024   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8025     {
8026       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8027       for(std::size_t j=0;j<sz;j++)
8028         {
8029           if (j%2)  // current point i is quadratic, next point i+1 is standard
8030             {
8031               i = sz+j;
8032               ip1 = (j+1)%sz; // ip1 = "i+1"
8033             }
8034           else      // current point i is standard, next point i+1 is quadratic
8035             {
8036               i = j;
8037               ip1 = j+sz;
8038             }
8039           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8040           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8041           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8042         }
8043       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8044     }
8045   return (ret>0.);
8046 }
8047
8048 /*!
8049  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8050  */
8051 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8052 {
8053   std::vector<std::pair<int,int> > edges;
8054   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8055   const int *bgFace=begin;
8056   for(std::size_t i=0;i<nbOfFaces;i++)
8057     {
8058       const int *endFace=std::find(bgFace+1,end,-1);
8059       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8060       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8061         {
8062           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8063           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8064             return false;
8065           edges.push_back(p1);
8066         }
8067       bgFace=endFace+1;
8068     }
8069   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8070 }
8071
8072 /*!
8073  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8074  */
8075 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8076 {
8077   double vec0[3],vec1[3];
8078   std::size_t sz=std::distance(begin,end);
8079   if(sz%2!=0)
8080     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8081   int nbOfNodes=(int)sz/2;
8082   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8083   const double *pt0=coords+3*begin[0];
8084   const double *pt1=coords+3*begin[nbOfNodes];
8085   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8086   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8087 }
8088
8089 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8090 {
8091   std::size_t sz=std::distance(begin,end);
8092   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8093   std::size_t nbOfNodes(sz/2);
8094   std::copy(begin,end,(int *)tmp);
8095   for(std::size_t j=1;j<nbOfNodes;j++)
8096     {
8097       begin[j]=tmp[nbOfNodes-j];
8098       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8099     }
8100 }
8101
8102 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8103 {
8104   std::size_t sz=std::distance(begin,end);
8105   if(sz!=4)
8106     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8107   double vec0[3],vec1[3];
8108   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8109   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]; 
8110   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;
8111 }
8112
8113 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8114 {
8115   std::size_t sz=std::distance(begin,end);
8116   if(sz!=5)
8117     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8118   double vec0[3];
8119   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8120   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8121   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8122 }
8123
8124 /*!
8125  * 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 ) 
8126  * 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
8127  * a 2D space.
8128  *
8129  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8130  * \param [in] coords the coordinates with nb of components exactly equal to 3
8131  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8132  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8133  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8134  */
8135 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8136 {
8137   int nbFaces=std::count(begin+1,end,-1)+1;
8138   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8139   double *vPtr=v->getPointer();
8140   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8141   double *pPtr=p->getPointer();
8142   const int *stFaceConn=begin+1;
8143   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8144     {
8145       const int *endFaceConn=std::find(stFaceConn,end,-1);
8146       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8147       stFaceConn=endFaceConn+1;
8148     }
8149   pPtr=p->getPointer(); vPtr=v->getPointer();
8150   DataArrayInt *comm1=0,*commI1=0;
8151   v->findCommonTuples(eps,-1,comm1,commI1);
8152   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8153   const int *comm1Ptr=comm1->getConstPointer();
8154   const int *commI1Ptr=commI1->getConstPointer();
8155   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8156   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8157   //
8158   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8159   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8160   mm->finishInsertingCells();
8161   //
8162   for(int i=0;i<nbOfGrps1;i++)
8163     {
8164       int vecId=comm1Ptr[commI1Ptr[i]];
8165       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8166       DataArrayInt *comm2=0,*commI2=0;
8167       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8168       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8169       const int *comm2Ptr=comm2->getConstPointer();
8170       const int *commI2Ptr=commI2->getConstPointer();
8171       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8172       for(int j=0;j<nbOfGrps2;j++)
8173         {
8174           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8175             {
8176               res->insertAtTheEnd(begin,end);
8177               res->pushBackSilent(-1);
8178             }
8179           else
8180             {
8181               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8182               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8183               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8184               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8185               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8186               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8187               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8188               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8189               const int *idsNodePtr=idsNode->getConstPointer();
8190               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];
8191               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8192               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8193               if(std::abs(norm)>eps)
8194                 {
8195                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8196                   mm3->rotate(center,vec,angle);
8197                 }
8198               mm3->changeSpaceDimension(2);
8199               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8200               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8201               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8202               int nbOfCells=mm4->getNumberOfCells();
8203               for(int k=0;k<nbOfCells;k++)
8204                 {
8205                   int l=0;
8206                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8207                     res->pushBackSilent(idsNodePtr[*work]);
8208                   res->pushBackSilent(-1);
8209                 }
8210             }
8211         }
8212     }
8213   res->popBackSilent();
8214 }
8215
8216 /*!
8217  * 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
8218  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8219  * 
8220  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8221  * \param [in] coords coordinates expected to have 3 components.
8222  * \param [in] begin start of the nodal connectivity of the face.
8223  * \param [in] end end of the nodal connectivity (excluded) of the face.
8224  * \param [out] v the normalized vector of size 3
8225  * \param [out] p the pos of plane
8226  */
8227 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8228 {
8229   std::size_t nbPoints=std::distance(begin,end);
8230   if(nbPoints<3)
8231     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8232   double vec[3]={0.,0.,0.};
8233   std::size_t j=0;
8234   bool refFound=false;
8235   for(;j<nbPoints-1 && !refFound;j++)
8236     {
8237       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8238       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8239       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8240       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8241       if(norm>eps)
8242         {
8243           refFound=true;
8244           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8245         }
8246     }
8247   for(std::size_t i=j;i<nbPoints-1;i++)
8248     {
8249       double curVec[3];
8250       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8251       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8252       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8253       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8254       if(norm<eps)
8255         continue;
8256       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8257       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];
8258       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8259       if(norm>eps)
8260         {
8261           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8262           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8263           return ;
8264         }
8265     }
8266   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8267 }
8268
8269 /*!
8270  * This method tries to obtain a well oriented polyhedron.
8271  * If the algorithm fails, an exception will be thrown.
8272  */
8273 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8274 {
8275   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8276   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8277   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8278   isPerm[0]=true;
8279   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8280   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8281   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8282   //
8283   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8284     {
8285       bgFace=begin;
8286       std::size_t smthChanged=0;
8287       for(std::size_t i=0;i<nbOfFaces;i++)
8288         {
8289           endFace=std::find(bgFace+1,end,-1);
8290           nbOfEdgesInFace=std::distance(bgFace,endFace);
8291           if(!isPerm[i])
8292             {
8293               bool b;
8294               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8295                 {
8296                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8297                   std::pair<int,int> p2(p1.second,p1.first);
8298                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8299                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8300                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8301                 }
8302               if(isPerm[i])
8303                 { 
8304                   if(!b)
8305                     std::reverse(bgFace+1,endFace);
8306                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8307                     {
8308                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8309                       std::pair<int,int> p2(p1.second,p1.first);
8310                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8311                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8312                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8313                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8314                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8315                       if(it!=edgesOK.end())
8316                         {
8317                           edgesOK.erase(it);
8318                           edgesFinished.push_back(p1);
8319                         }
8320                       else
8321                         edgesOK.push_back(p1);
8322                     }
8323                 }
8324             }
8325           bgFace=endFace+1;
8326         }
8327       if(smthChanged==0)
8328         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8329     }
8330   if(!edgesOK.empty())
8331     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8332   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8333     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8334       bgFace=begin;
8335       for(std::size_t i=0;i<nbOfFaces;i++)
8336         {
8337           endFace=std::find(bgFace+1,end,-1);
8338           std::reverse(bgFace+1,endFace);
8339           bgFace=endFace+1;
8340         }
8341     }
8342 }
8343
8344 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8345 {
8346   int nbOfNodesExpected(skin->getNumberOfNodes());
8347   const int *n2oPtr(n2o->getConstPointer());
8348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8349   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8350   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8351   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8352   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8353   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8354   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8355   if(nbOfNodesExpected<1)
8356     return ret.retn();
8357   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8358   *work++=n2oPtr[prevNode];
8359   for(int i=1;i<nbOfNodesExpected;i++)
8360     {
8361       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8362         {
8363           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8364           conn.erase(prevNode);
8365           if(conn.size()==1)
8366             {
8367               int curNode(*(conn.begin()));
8368               *work++=n2oPtr[curNode];
8369               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8370               shar.erase(prevCell);
8371               if(shar.size()==1)
8372                 {
8373                   prevCell=*(shar.begin());
8374                   prevNode=curNode;
8375                 }
8376               else
8377                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8378             }
8379           else
8380             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8381         }
8382       else
8383         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8384     }
8385   return ret.retn();
8386 }
8387
8388 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8389 {
8390   int nbOfNodesExpected(skin->getNumberOfNodes());
8391   int nbOfTurn(nbOfNodesExpected/2);
8392   const int *n2oPtr(n2o->getConstPointer());
8393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8394   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8395   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8396   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8397   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8399   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8400   if(nbOfNodesExpected<1)
8401     return ret.retn();
8402   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8403   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8404   for(int i=1;i<nbOfTurn;i++)
8405     {
8406       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8407         {
8408           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8409           conn.erase(prevNode);
8410           if(conn.size()==1)
8411             {
8412               int curNode(*(conn.begin()));
8413               *work=n2oPtr[curNode];
8414               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8415               shar.erase(prevCell);
8416               if(shar.size()==1)
8417                 {
8418                   int curCell(*(shar.begin()));
8419                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8420                   prevCell=curCell;
8421                   prevNode=curNode;
8422                   work++;
8423                 }
8424               else
8425                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8426             }
8427           else
8428             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8429         }
8430       else
8431         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8432     }
8433   return ret.retn();
8434 }
8435
8436 /*!
8437  * This method makes the assumption spacedimension == meshdimension == 2.
8438  * This method works only for linear cells.
8439  * 
8440  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8441  */
8442 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8443 {
8444   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8445     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8446   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8447   int oldNbOfNodes(skin->getNumberOfNodes());
8448   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8449   int nbOfNodesExpected(skin->getNumberOfNodes());
8450   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8451   int nbCells(skin->getNumberOfCells());
8452   if(nbCells==nbOfNodesExpected)
8453     return buildUnionOf2DMeshLinear(skin,n2o);
8454   else if(2*nbCells==nbOfNodesExpected)
8455     return buildUnionOf2DMeshQuadratic(skin,n2o);
8456   else
8457     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8458 }
8459
8460 /*!
8461  * This method makes the assumption spacedimension == meshdimension == 3.
8462  * This method works only for linear cells.
8463  * 
8464  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8465  */
8466 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8467 {
8468   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8469     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8470   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8471   const int *conn=m->getNodalConnectivity()->getConstPointer();
8472   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8473   int nbOfCells=m->getNumberOfCells();
8474   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8475   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8476   if(nbOfCells<1)
8477     return ret.retn();
8478   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8479   for(int i=1;i<nbOfCells;i++)
8480     {
8481       *work++=-1;
8482       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8483     }
8484   return ret.retn();
8485 }
8486
8487 /*!
8488  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8489  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8490  */
8491 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8492 {
8493   double *w=zipFrmt;
8494   if(spaceDim==3)
8495     for(int i=0;i<nbOfNodesInCell;i++)
8496       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8497   else if(spaceDim==2)
8498     {
8499       for(int i=0;i<nbOfNodesInCell;i++)
8500         {
8501           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8502           *w++=0.;
8503         }
8504     }
8505   else
8506     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8507 }
8508
8509 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8510 {
8511   int nbOfCells=getNumberOfCells();
8512   if(nbOfCells<=0)
8513     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8514   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};
8515   ofs << "  <" << getVTKDataSetType() << ">\n";
8516   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8517   ofs << "      <PointData>\n" << pointData << std::endl;
8518   ofs << "      </PointData>\n";
8519   ofs << "      <CellData>\n" << cellData << std::endl;
8520   ofs << "      </CellData>\n";
8521   ofs << "      <Points>\n";
8522   if(getSpaceDimension()==3)
8523     _coords->writeVTK(ofs,8,"Points",byteData);
8524   else
8525     {
8526       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8527       coo->writeVTK(ofs,8,"Points",byteData);
8528     }
8529   ofs << "      </Points>\n";
8530   ofs << "      <Cells>\n";
8531   const int *cPtr=_nodal_connec->getConstPointer();
8532   const int *cIPtr=_nodal_connec_index->getConstPointer();
8533   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8534   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8535   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8536   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8537   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8538   int szFaceOffsets=0,szConn=0;
8539   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8540     {
8541       *w2=cPtr[cIPtr[i]];
8542       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8543         {
8544           *w1=-1;
8545           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8546           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8547         }
8548       else
8549         {
8550           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8551           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8552           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8553           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8554           w4=std::copy(c.begin(),c.end(),w4);
8555         }
8556     }
8557   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8558   types->writeVTK(ofs,8,"UInt8","types",byteData);
8559   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8560   if(szFaceOffsets!=0)
8561     {//presence of Polyhedra
8562       connectivity->reAlloc(szConn);
8563       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8564       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8565       w1=faces->getPointer();
8566       for(int i=0;i<nbOfCells;i++)
8567         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8568           {
8569             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8570             *w1++=nbFaces;
8571             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8572             for(int j=0;j<nbFaces;j++)
8573               {
8574                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8575                 *w1++=(int)std::distance(w6,w5);
8576                 w1=std::copy(w6,w5,w1);
8577                 w6=w5+1;
8578               }
8579           }
8580       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8581     }
8582   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8583   ofs << "      </Cells>\n";
8584   ofs << "    </Piece>\n";
8585   ofs << "  </" << getVTKDataSetType() << ">\n";
8586 }
8587
8588 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8589 {
8590   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8591   if(_mesh_dim==-2)
8592     { stream << " Not set !"; return ; }
8593   stream << " Mesh dimension : " << _mesh_dim << ".";
8594   if(_mesh_dim==-1)
8595     return ;
8596   if(!_coords)
8597     { stream << " No coordinates set !"; return ; }
8598   if(!_coords->isAllocated())
8599     { stream << " Coordinates set but not allocated !"; return ; }
8600   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8601   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8602   if(!_nodal_connec_index)
8603     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8604   if(!_nodal_connec_index->isAllocated())
8605     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8606   int lgth=_nodal_connec_index->getNumberOfTuples();
8607   int cpt=_nodal_connec_index->getNumberOfComponents();
8608   if(cpt!=1 || lgth<1)
8609     return ;
8610   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8611 }
8612
8613 std::string MEDCouplingUMesh::getVTKDataSetType() const
8614 {
8615   return std::string("UnstructuredGrid");
8616 }
8617
8618 /*!
8619  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8620  * returns a result mesh constituted by polygons.
8621  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8622  * all nodes from m2.
8623  * The meshes should be in 2D space. In
8624  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8625  * meshes.
8626  *  \param [in] m1 - the first input mesh which is a partitioned object.
8627  *  \param [in] m2 - the second input mesh which is a partition tool.
8628  *  \param [in] eps - precision used to detect coincident mesh entities.
8629  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8630  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8631  *         this array using decrRef() as it is no more needed.
8632  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8633  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8634  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8635  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8636  *         it is no more needed.  
8637  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8638  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8639  *         is no more needed.  
8640  *  \throw If the coordinates array is not set in any of the meshes.
8641  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8642  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8643  */
8644 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8645                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8646 {
8647   m1->checkFullyDefined();
8648   m2->checkFullyDefined();
8649   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8650     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8651
8652   // Step 1: compute all edge intersections (new nodes)
8653   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8654   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8655   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8656   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8657   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8658   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8659   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8660                                       m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8661                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8662   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8663   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8664   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8665
8666   // Step 2: re-order newly created nodes according to the ordering found in m2
8667   std::vector< std::vector<int> > intersectEdge2;
8668   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8669   subDiv2.clear(); dd5=0; dd6=0;
8670
8671   // Step 3:
8672   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8673   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8674   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8675                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8676
8677   // Step 4: Prepare final result:
8678   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8679   addCooDa->alloc((int)(addCoo.size())/2,2);
8680   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8681   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8682   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8683   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8684   std::vector<const DataArrayDouble *> coordss(4);
8685   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8686   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8687   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8688   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8690   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8691   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8692   ret->setConnectivity(conn,connI,true);
8693   ret->setCoords(coo);
8694   cellNb1=c1.retn(); cellNb2=c2.retn();
8695   return ret.retn();
8696 }
8697
8698
8699 /**
8700  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8701  * (newly created) nodes corresponding to the edge intersections.
8702  * Output params:
8703  * @param[out] cr, crI connectivity of the resulting mesh
8704  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8705  * TODO: describe input parameters
8706  */
8707 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8708                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8709                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8710                                                          const std::vector<double>& addCoords,
8711                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8712 {
8713   static const int SPACEDIM=2;
8714   const double *coo1=m1->getCoords()->getConstPointer();
8715   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8716   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8717   int offset1=m1->getNumberOfNodes();
8718   const double *coo2=m2->getCoords()->getConstPointer();
8719   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8720   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8721   int offset2=offset1+m2->getNumberOfNodes();
8722   int offset3=offset2+((int)addCoords.size())/2;
8723   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8724   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8725   // Here a BBTree on 2D-cells, not on segments:
8726   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8727   int ncell1=m1->getNumberOfCells();
8728   crI.push_back(0);
8729   for(int i=0;i<ncell1;i++)
8730     {
8731       std::vector<int> candidates2;
8732       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8733       std::map<INTERP_KERNEL::Node *,int> mapp;
8734       std::map<int,INTERP_KERNEL::Node *> mappRev;
8735       INTERP_KERNEL::QuadraticPolygon pol1;
8736       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8737       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8738       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8739       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8740       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8741       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8742                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8743       //
8744       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
8745       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8746       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8747       for(it1.first();!it1.finished();it1.next())
8748         edges1.insert(it1.current()->getPtr());
8749       //
8750       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8751       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8752       int ii=0;
8753       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8754         {
8755           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8756           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8757           // Complete mapping with elements coming from the current cell it2 in mesh2:
8758           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8759           // pol2 is the new QP in the final merged result.
8760           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8761                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8762         }
8763       ii=0;
8764       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8765         {
8766           pol1.initLocationsWithOther(pol2s[ii]);
8767           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8768           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8769           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8770         }
8771       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8772       // by m2 but that we still want to keep in the final result.
8773       if(!edges1.empty())
8774         {
8775           try
8776             {
8777               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8778             }
8779           catch(INTERP_KERNEL::Exception& e)
8780             {
8781               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();
8782               throw INTERP_KERNEL::Exception(oss.str().c_str());
8783             }
8784         }
8785       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8786         (*it).second->decrRef();
8787     }
8788 }
8789
8790 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8791 {
8792   std::map<INTERP_KERNEL::Node *,int>::const_iterator it(m.find(n));
8793   if(it==m.end())
8794     throw INTERP_KERNEL::Exception("Internal error in remapping !");
8795   int v((*it).second);
8796   if(v==forbVal0 || v==forbVal1)
8797     return ;
8798   if(std::find(isect.begin(),isect.end(),v)==isect.end())
8799     isect.push_back(v);
8800 }
8801
8802 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8803 {
8804   int sz(c.size());
8805   if(sz<=1)
8806     return false;
8807   bool presenceOfOn(false);
8808   for(int i=0;i<sz;i++)
8809     {
8810       INTERP_KERNEL::ElementaryEdge *e(c[i]);
8811       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
8812         continue ;
8813       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
8814       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
8815     }
8816   return presenceOfOn;
8817 }
8818
8819 /**
8820  * 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.
8821  * 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.
8822  * 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.
8823  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
8824  *
8825  * \return int - the number of new nodes created (in most of cases 0).
8826  * 
8827  * \throw If \a this is not coherent.
8828  * \throw If \a this has not spaceDim equal to 2.
8829  * \throw If \a this has not meshDim equal to 2.
8830  * \throw If some subcells needed to be split are orphan.
8831  * \sa MEDCouplingUMesh::conformize2D
8832  */
8833 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
8834 {
8835   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
8836     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
8837   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
8838   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8840   if(midOpt==0 && midOptI==0)
8841     {
8842       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
8843       return 0;
8844     }
8845   else if(midOpt!=0 && midOptI!=0)
8846     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
8847   else
8848     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
8849 }
8850
8851 /*!
8852  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
8853  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
8854  * 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
8855  * 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).
8856  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
8857  * The modified cells if any are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the 
8858  *
8859  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
8860  * This method expects that all nodes in \a this are not closer than \a eps.
8861  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
8862  * 
8863  * \param [in] eps the relative error to detect merged edges.
8864  * \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
8865  *                           that the user is expected to deal with.
8866  *
8867  * \throw If \a this is not coherent.
8868  * \throw If \a this has not spaceDim equal to 2.
8869  * \throw If \a this has not meshDim equal to 2.
8870  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
8871  */
8872 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
8873 {
8874   static const int SPACEDIM=2;
8875   checkCoherency();
8876   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8877     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
8879   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
8880   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
8881   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
8882   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
8883   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
8884   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
8885   std::vector<double> addCoo;
8886   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
8887   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8888   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8889   for(int i=0;i<nDescCell;i++)
8890     {
8891       std::vector<int> candidates;
8892       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
8893       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8894         if(*it>i)
8895           {
8896             std::map<INTERP_KERNEL::Node *,int> m;
8897             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
8898               *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
8899             INTERP_KERNEL::MergePoints merge;
8900             INTERP_KERNEL::QuadraticPolygon c1,c2;
8901             e1->intersectWith(e2,merge,c1,c2);
8902             e1->decrRef(); e2->decrRef();
8903             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
8904               overlapEdge[i].push_back(*it);
8905             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
8906               overlapEdge[*it].push_back(i);
8907             for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8908               (*it2).first->decrRef();
8909           }
8910     }
8911   // splitting done. sort intersect point in intersectEdge.
8912   std::vector< std::vector<int> > middle(nDescCell);
8913   int nbOf2DCellsToBeSplit(0);
8914   bool middleNeedsToBeUsed(false);
8915   std::vector<bool> cells2DToTreat(nDescCell,false);
8916   for(int i=0;i<nDescCell;i++)
8917     {
8918       std::vector<int>& isect(intersectEdge[i]);
8919       int sz((int)isect.size());
8920       if(sz>1)
8921         {
8922           std::map<INTERP_KERNEL::Node *,int> m;
8923           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
8924           e->sortSubNodesAbs(coords,isect);
8925           e->decrRef();
8926           for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8927             (*it2).first->decrRef();
8928         }
8929       if(sz!=0)
8930         {
8931           int idx0(rdi[i]),idx1(rdi[i+1]);
8932           if(idx1-idx0!=1)
8933             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
8934           if(!cells2DToTreat[rd[idx0]])
8935             {
8936               cells2DToTreat[rd[idx0]]=true;
8937               nbOf2DCellsToBeSplit++;
8938             }
8939           // try to reuse at most eventual 'middle' of SEG3
8940           std::vector<int>& mid(middle[i]);
8941           mid.resize(sz+1,-1);
8942           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
8943             {
8944               middleNeedsToBeUsed=true;
8945               const std::vector<int>& candidates(overlapEdge[i]);
8946               std::vector<int> trueCandidates;
8947               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
8948                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
8949                   trueCandidates.push_back(*itc);
8950               int stNode(c[ci[i]+1]),endNode(isect[0]);
8951               for(int j=0;j<sz+1;j++)
8952                 {
8953                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
8954                     {
8955                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
8956                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
8957                         { mid[j]=*itc; break; }
8958                     }
8959                   stNode=endNode;
8960                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
8961                 }
8962             }
8963         }
8964     }
8965   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
8966   if(nbOf2DCellsToBeSplit==0)
8967     return ret.retn();
8968   //
8969   int *retPtr(ret->getPointer());
8970   for(int i=0;i<nCell;i++)
8971     if(cells2DToTreat[i])
8972       *retPtr++=i;
8973   //
8974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
8975   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
8976   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
8977   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
8978   if(middleNeedsToBeUsed)
8979     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
8980   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
8981   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
8982   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.
8983   setPartOfMySelf(ret->begin(),ret->end(),*modif);
8984   {
8985     bool areNodesMerged; int newNbOfNodes;
8986     if(nbOfNodesCreated!=0)
8987       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
8988   }
8989   return ret.retn();
8990 }
8991
8992 /*!
8993  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8994  * It builds the descending connectivity of the two meshes, and then using a binary tree
8995  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
8996  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
8997  */
8998 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8999                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
9000                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
9001                                                    std::vector<double>& addCoo,
9002                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
9003                                                    throw(INTERP_KERNEL::Exception)
9004 {
9005   static const int SPACEDIM=2;
9006   // Build desc connectivity
9007   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
9008   desc2=DataArrayInt::New();
9009   descIndx2=DataArrayInt::New();
9010   revDesc2=DataArrayInt::New();
9011   revDescIndx2=DataArrayInt::New();
9012   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9013   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
9014   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
9015   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
9016   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
9017   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
9018   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
9019
9020   // Build BB tree of all edges in the tool mesh (second mesh)
9021   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9022   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9023   int nDescCell1=m1Desc->getNumberOfCells();
9024   int nDescCell2=m2Desc->getNumberOfCells();
9025   intersectEdge1.resize(nDescCell1);
9026   colinear2.resize(nDescCell2);
9027   subDiv2.resize(nDescCell2);
9028   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9029
9030   std::vector<int> candidates1(1);
9031   int offset1=m1->getNumberOfNodes();
9032   int offset2=offset1+m2->getNumberOfNodes();
9033   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
9034     {
9035       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9036       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9037       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9038         {
9039           std::map<INTERP_KERNEL::Node *,int> map1,map2;
9040           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9041           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9042           candidates1[0]=i;
9043           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
9044           // 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
9045           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
9046           std::set<INTERP_KERNEL::Node *> nodes;
9047           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
9048           std::size_t szz(nodes.size());
9049           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
9050           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
9051           for(std::size_t iii=0;iii<szz;iii++,itt++)
9052             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
9053           // end of protection
9054           // Performs egde cutting:
9055           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
9056           delete pol2;
9057           delete pol1;
9058         }
9059       else
9060         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9061     }
9062   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
9063   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
9064 }
9065
9066 /*!
9067  * This method performs the 2nd step of Partition of 2D mesh.
9068  * This method has 4 inputs :
9069  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
9070  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
9071  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
9072  * 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'
9073  * Nodes end up lying consecutively on a cutted edge.
9074  * \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.
9075  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
9076  * \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.
9077  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
9078  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
9079  */
9080 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9081       const std::vector<double>& addCoo,
9082       const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
9083 {
9084   int offset1=m1->getNumberOfNodes();
9085   int ncell=m2->getNumberOfCells();
9086   const int *c=m2->getNodalConnectivity()->getConstPointer();
9087   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
9088   const double *coo=m2->getCoords()->getConstPointer();
9089   const double *cooBis=m1->getCoords()->getConstPointer();
9090   int offset2=offset1+m2->getNumberOfNodes();
9091   intersectEdge.resize(ncell);
9092   for(int i=0;i<ncell;i++,cI++)
9093     {
9094       const std::vector<int>& divs=subDiv[i];
9095       int nnode=cI[1]-cI[0]-1;
9096       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
9097       std::map<INTERP_KERNEL::Node *, int> mapp22;
9098       for(int j=0;j<nnode;j++)
9099         {
9100           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
9101           int nnid=c[(*cI)+j+1];
9102           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
9103           mapp22[nn]=nnid+offset1;
9104         }
9105       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
9106       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
9107         ((*it).second.first)->decrRef();
9108       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
9109       std::map<INTERP_KERNEL::Node *,int> mapp3;
9110       for(std::size_t j=0;j<divs.size();j++)
9111         {
9112           int id=divs[j];
9113           INTERP_KERNEL::Node *tmp=0;
9114           if(id<offset1)
9115             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
9116           else if(id<offset2)
9117             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
9118           else
9119             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
9120           addNodes[j]=tmp;
9121           mapp3[tmp]=id;
9122         }
9123       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
9124       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
9125         (*it)->decrRef();
9126       e->decrRef();
9127     }
9128 }
9129
9130 /*!
9131  * 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).
9132  * 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
9133  * with a plane. The result will be put in 'cut3DSuf' out parameter.
9134  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
9135  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
9136  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
9137  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
9138  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
9139  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
9140  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
9141  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
9142  * \param [out] cut3DSuf input/output param.
9143  */
9144 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
9145                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
9146                                                    const int *desc, const int *descIndx, 
9147                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
9148 {
9149   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
9150   int nbOf3DSurfCell=(int)cut3DSurf.size();
9151   for(int i=0;i<nbOf3DSurfCell;i++)
9152     {
9153       std::vector<int> res;
9154       int offset=descIndx[i];
9155       int nbOfSeg=descIndx[i+1]-offset;
9156       for(int j=0;j<nbOfSeg;j++)
9157         {
9158           int edgeId=desc[offset+j];
9159           int status=cut3DCurve[edgeId];
9160           if(status!=-2)
9161             {
9162               if(status>-1)
9163                 res.push_back(status);
9164               else
9165                 {
9166                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
9167                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
9168                 }
9169             }
9170         }
9171       switch(res.size())
9172         {
9173         case 2:
9174           {
9175             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9176             break;
9177           }
9178         case 1:
9179         case 0:
9180           {
9181             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
9182             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
9183             if(res.size()==2)
9184               {
9185                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9186               }
9187             else
9188               {
9189                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
9190               }
9191             break;
9192           }
9193         default:
9194           {// case when plane is on a multi colinear edge of a polyhedron
9195             if((int)res.size()==2*nbOfSeg)
9196               {
9197                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
9198               }
9199             else
9200               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
9201           }
9202         }
9203     }
9204 }
9205
9206 /*!
9207  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
9208  * 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).
9209  * 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
9210  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
9211  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
9212  * \param desc is the descending connectivity 3D->3DSurf
9213  * \param descIndx is the descending connectivity index 3D->3DSurf
9214  */
9215 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
9216                                                   const int *desc, const int *descIndx,
9217                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
9218 {
9219   checkFullyDefined();
9220   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9221     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
9222   const int *nodal3D=_nodal_connec->getConstPointer();
9223   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
9224   int nbOfCells=getNumberOfCells();
9225   for(int i=0;i<nbOfCells;i++)
9226     {
9227       std::map<int, std::set<int> > m;
9228       int offset=descIndx[i];
9229       int nbOfFaces=descIndx[i+1]-offset;
9230       int start=-1;
9231       int end=-1;
9232       for(int j=0;j<nbOfFaces;j++)
9233         {
9234           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
9235           if(p.first!=-1 && p.second!=-1)
9236             {
9237               if(p.first!=-2)
9238                 {
9239                   start=p.first; end=p.second;
9240                   m[p.first].insert(p.second);
9241                   m[p.second].insert(p.first);
9242                 }
9243               else
9244                 {
9245                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
9246                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
9247                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
9248                   INTERP_KERNEL::NormalizedCellType cmsId;
9249                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
9250                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
9251                   for(unsigned k=0;k<nbOfNodesSon;k++)
9252                     {
9253                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
9254                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
9255                     }
9256                 }
9257             }
9258         }
9259       if(m.empty())
9260         continue;
9261       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
9262       int prev=end;
9263       while(end!=start)
9264         {
9265           std::map<int, std::set<int> >::const_iterator it=m.find(start);
9266           const std::set<int>& s=(*it).second;
9267           std::set<int> s2; s2.insert(prev);
9268           std::set<int> s3;
9269           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
9270           if(s3.size()==1)
9271             {
9272               int val=*s3.begin();
9273               conn.push_back(start);
9274               prev=start;
9275               start=val;
9276             }
9277           else
9278             start=end;
9279         }
9280       conn.push_back(end);
9281       if(conn.size()>3)
9282         {
9283           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
9284           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
9285           cellIds->pushBackSilent(i);
9286         }
9287     }
9288 }
9289
9290 /*!
9291  * 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
9292  * 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
9293  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9294  * 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
9295  * 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.
9296  * 
9297  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9298  */
9299 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9300 {
9301   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9302   if(sz>=4)
9303     {
9304       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9305       if(cm.getDimension()==2)
9306         {
9307           const int *node=nodalConnBg+1;
9308           int startNode=*node++;
9309           double refX=coords[2*startNode];
9310           for(;node!=nodalConnEnd;node++)
9311             {
9312               if(coords[2*(*node)]<refX)
9313                 {
9314                   startNode=*node;
9315                   refX=coords[2*startNode];
9316                 }
9317             }
9318           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9319           refX=1e300;
9320           double tmp1;
9321           double tmp2[2];
9322           double angle0=-M_PI/2;
9323           //
9324           int nextNode=-1;
9325           int prevNode=-1;
9326           double resRef;
9327           double angleNext=0.;
9328           while(nextNode!=startNode)
9329             {
9330               nextNode=-1;
9331               resRef=1e300;
9332               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9333                 {
9334                   if(*node!=tmpOut.back() && *node!=prevNode)
9335                     {
9336                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9337                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9338                       double res;
9339                       if(angleM<=angle0)
9340                         res=angle0-angleM;
9341                       else
9342                         res=angle0-angleM+2.*M_PI;
9343                       if(res<resRef)
9344                         {
9345                           nextNode=*node;
9346                           resRef=res;
9347                           angleNext=angleM;
9348                         }
9349                     }
9350                 }
9351               if(nextNode!=startNode)
9352                 {
9353                   angle0=angleNext-M_PI;
9354                   if(angle0<-M_PI)
9355                     angle0+=2*M_PI;
9356                   prevNode=tmpOut.back();
9357                   tmpOut.push_back(nextNode);
9358                 }
9359             }
9360           std::vector<int> tmp3(2*(sz-1));
9361           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9362           std::copy(nodalConnBg+1,nodalConnEnd,it);
9363           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9364             {
9365               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9366               return false;
9367             }
9368           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9369             {
9370               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9371               return false;
9372             }
9373           else
9374             {
9375               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9376               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9377               return true;
9378             }
9379         }
9380       else
9381         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9382     }
9383   else
9384     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9385 }
9386
9387 /*!
9388  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9389  * 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.
9390  * 
9391  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9392  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9393  * \param [in,out] arr array in which the remove operation will be done.
9394  * \param [in,out] arrIndx array in the remove operation will modify
9395  * \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])
9396  * \return true if \b arr and \b arrIndx have been modified, false if not.
9397  */
9398 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9399 {
9400   if(!arrIndx || !arr)
9401     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9402   if(offsetForRemoval<0)
9403     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9404   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9405   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9406   int *arrIPtr=arrIndx->getPointer();
9407   *arrIPtr++=0;
9408   int previousArrI=0;
9409   const int *arrPtr=arr->getConstPointer();
9410   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9411   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9412     {
9413       if(*arrIPtr-previousArrI>offsetForRemoval)
9414         {
9415           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9416             {
9417               if(s.find(*work)==s.end())
9418                 arrOut.push_back(*work);
9419             }
9420         }
9421       previousArrI=*arrIPtr;
9422       *arrIPtr=(int)arrOut.size();
9423     }
9424   if(arr->getNumberOfTuples()==(int)arrOut.size())
9425     return false;
9426   arr->alloc((int)arrOut.size(),1);
9427   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9428   return true;
9429 }
9430
9431 /*!
9432  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9433  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9434  * The selection of extraction is done standardly in new2old format.
9435  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9436  *
9437  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9438  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9439  * \param [in] arrIn arr origin array from which the extraction will be done.
9440  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9441  * \param [out] arrOut the resulting array
9442  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9443  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9444  */
9445 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9446                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9447 {
9448   if(!arrIn || !arrIndxIn)
9449     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9450   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9451   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9452     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9453   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9454   const int *arrInPtr=arrIn->getConstPointer();
9455   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9456   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9457   if(nbOfGrps<0)
9458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9459   int maxSizeOfArr=arrIn->getNumberOfTuples();
9460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9461   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9462   arrIo->alloc((int)(sz+1),1);
9463   const int *idsIt=idsOfSelectBg;
9464   int *work=arrIo->getPointer();
9465   *work++=0;
9466   int lgth=0;
9467   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9468     {
9469       if(*idsIt>=0 && *idsIt<nbOfGrps)
9470         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9471       else
9472         {
9473           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9474           throw INTERP_KERNEL::Exception(oss.str().c_str());
9475         }
9476       if(lgth>=work[-1])
9477         *work=lgth;
9478       else
9479         {
9480           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9481           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9482           throw INTERP_KERNEL::Exception(oss.str().c_str());
9483         }
9484     }
9485   arro->alloc(lgth,1);
9486   work=arro->getPointer();
9487   idsIt=idsOfSelectBg;
9488   for(std::size_t i=0;i<sz;i++,idsIt++)
9489     {
9490       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9491         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9492       else
9493         {
9494           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9495           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9496           throw INTERP_KERNEL::Exception(oss.str().c_str());
9497         }
9498     }
9499   arrOut=arro.retn();
9500   arrIndexOut=arrIo.retn();
9501 }
9502
9503 /*!
9504  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9505  * 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 ).
9506  * The selection of extraction is done standardly in new2old format.
9507  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9508  *
9509  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9510  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9511  * \param [in] arrIn arr origin array from which the extraction will be done.
9512  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9513  * \param [out] arrOut the resulting array
9514  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9515  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9516  */
9517 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9518                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9519 {
9520   if(!arrIn || !arrIndxIn)
9521     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9522   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9523   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9524     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9525   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9526   const int *arrInPtr=arrIn->getConstPointer();
9527   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9528   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9529   if(nbOfGrps<0)
9530     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9531   int maxSizeOfArr=arrIn->getNumberOfTuples();
9532   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9533   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9534   arrIo->alloc((int)(sz+1),1);
9535   int idsIt=idsOfSelectStart;
9536   int *work=arrIo->getPointer();
9537   *work++=0;
9538   int lgth=0;
9539   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9540     {
9541       if(idsIt>=0 && idsIt<nbOfGrps)
9542         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9543       else
9544         {
9545           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9546           throw INTERP_KERNEL::Exception(oss.str().c_str());
9547         }
9548       if(lgth>=work[-1])
9549         *work=lgth;
9550       else
9551         {
9552           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9553           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9554           throw INTERP_KERNEL::Exception(oss.str().c_str());
9555         }
9556     }
9557   arro->alloc(lgth,1);
9558   work=arro->getPointer();
9559   idsIt=idsOfSelectStart;
9560   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9561     {
9562       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9563         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9564       else
9565         {
9566           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9567           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9568           throw INTERP_KERNEL::Exception(oss.str().c_str());
9569         }
9570     }
9571   arrOut=arro.retn();
9572   arrIndexOut=arrIo.retn();
9573 }
9574
9575 /*!
9576  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9577  * 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
9578  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9579  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9580  *
9581  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9582  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9583  * \param [in] arrIn arr origin array from which the extraction will be done.
9584  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9585  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9586  * \param [in] srcArrIndex index array of \b srcArr
9587  * \param [out] arrOut the resulting array
9588  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9589  * 
9590  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9591  */
9592 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9593                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9594                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9595 {
9596   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9597     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9598   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9599   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9600   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9601   std::vector<bool> v(nbOfTuples,true);
9602   int offset=0;
9603   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9604   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9605   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9606     {
9607       if(*it>=0 && *it<nbOfTuples)
9608         {
9609           v[*it]=false;
9610           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9611         }
9612       else
9613         {
9614           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9615           throw INTERP_KERNEL::Exception(oss.str().c_str());
9616         }
9617     }
9618   srcArrIndexPtr=srcArrIndex->getConstPointer();
9619   arrIo->alloc(nbOfTuples+1,1);
9620   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9621   const int *arrInPtr=arrIn->getConstPointer();
9622   const int *srcArrPtr=srcArr->getConstPointer();
9623   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9624   int *arroPtr=arro->getPointer();
9625   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9626     {
9627       if(v[ii])
9628         {
9629           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9630           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9631         }
9632       else
9633         {
9634           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9635           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9636           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9637         }
9638     }
9639   arrOut=arro.retn();
9640   arrIndexOut=arrIo.retn();
9641 }
9642
9643 /*!
9644  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9645  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9646  *
9647  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9648  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9649  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9650  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9651  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9652  * \param [in] srcArrIndex index array of \b srcArr
9653  * 
9654  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9655  */
9656 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9657                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9658 {
9659   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9660     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9661   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9662   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9663   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9664   int *arrInOutPtr=arrInOut->getPointer();
9665   const int *srcArrPtr=srcArr->getConstPointer();
9666   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9667     {
9668       if(*it>=0 && *it<nbOfTuples)
9669         {
9670           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9671             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9672           else
9673             {
9674               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] !";
9675               throw INTERP_KERNEL::Exception(oss.str().c_str());
9676             }
9677         }
9678       else
9679         {
9680           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9681           throw INTERP_KERNEL::Exception(oss.str().c_str());
9682         }
9683     }
9684 }
9685
9686 /*!
9687  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9688  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9689  * 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]].
9690  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9691  * A negative value in \b arrIn means that it is ignored.
9692  * 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.
9693  * 
9694  * \param [in] arrIn arr origin array from which the extraction will be done.
9695  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9696  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9697  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9698  */
9699 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9700 {
9701   int seed=0,nbOfDepthPeelingPerformed=0;
9702   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9703 }
9704
9705 /*!
9706  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9707  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9708  * 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]].
9709  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9710  * A negative value in \b arrIn means that it is ignored.
9711  * 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.
9712  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9713  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9714  * \param [in] arrIn arr origin array from which the extraction will be done.
9715  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9716  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9717  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9718  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9719  * \sa MEDCouplingUMesh::partitionBySpreadZone
9720  */
9721 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9722 {
9723   nbOfDepthPeelingPerformed=0;
9724   if(!arrIndxIn)
9725     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9726   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9727   if(nbOfTuples<=0)
9728     {
9729       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9730       return ret;
9731     }
9732   //
9733   std::vector<bool> fetched(nbOfTuples,false);
9734   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9735 }
9736
9737 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9738 {
9739   nbOfDepthPeelingPerformed=0;
9740   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9742   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9743   std::vector<bool> fetched2(nbOfTuples,false);
9744   int i=0;
9745   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9746     {
9747       if(*seedElt>=0 && *seedElt<nbOfTuples)
9748         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9749       else
9750         { 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()); }
9751     }
9752   const int *arrInPtr=arrIn->getConstPointer();
9753   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9754   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9755   std::vector<int> idsToFetch1(seedBg,seedEnd);
9756   std::vector<int> idsToFetch2;
9757   std::vector<int> *idsToFetch=&idsToFetch1;
9758   std::vector<int> *idsToFetchOther=&idsToFetch2;
9759   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9760     {
9761       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9762         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9763           if(!fetched[*it2])
9764             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9765       std::swap(idsToFetch,idsToFetchOther);
9766       idsToFetchOther->clear();
9767       nbOfDepthPeelingPerformed++;
9768     }
9769   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9770   i=0;
9771   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9772   int *retPtr=ret->getPointer();
9773   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9774     if(*it)
9775       *retPtr++=i;
9776   return ret.retn();
9777 }
9778
9779 /*!
9780  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9781  * 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
9782  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9783  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9784  *
9785  * \param [in] start begin of set of ids of the input extraction (included)
9786  * \param [in] end end of set of ids of the input extraction (excluded)
9787  * \param [in] step step of the set of ids in range mode.
9788  * \param [in] arrIn arr origin array from which the extraction will be done.
9789  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9790  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9791  * \param [in] srcArrIndex index array of \b srcArr
9792  * \param [out] arrOut the resulting array
9793  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9794  * 
9795  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9796  */
9797 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9798                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9799                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9800 {
9801   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9802     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9803   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9804   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9805   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9806   int offset=0;
9807   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9808   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9809   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9810   int it=start;
9811   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9812     {
9813       if(it>=0 && it<nbOfTuples)
9814         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9815       else
9816         {
9817           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9818           throw INTERP_KERNEL::Exception(oss.str().c_str());
9819         }
9820     }
9821   srcArrIndexPtr=srcArrIndex->getConstPointer();
9822   arrIo->alloc(nbOfTuples+1,1);
9823   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9824   const int *arrInPtr=arrIn->getConstPointer();
9825   const int *srcArrPtr=srcArr->getConstPointer();
9826   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9827   int *arroPtr=arro->getPointer();
9828   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9829     {
9830       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9831       if(pos<0)
9832         {
9833           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9834           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9835         }
9836       else
9837         {
9838           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9839           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9840         }
9841     }
9842   arrOut=arro.retn();
9843   arrIndexOut=arrIo.retn();
9844 }
9845
9846 /*!
9847  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9848  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9849  *
9850  * \param [in] start begin of set of ids of the input extraction (included)
9851  * \param [in] end end of set of ids of the input extraction (excluded)
9852  * \param [in] step step of the set of ids in range mode.
9853  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9854  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9855  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9856  * \param [in] srcArrIndex index array of \b srcArr
9857  * 
9858  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9859  */
9860 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9861                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9862 {
9863   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9864     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9865   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9866   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9867   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9868   int *arrInOutPtr=arrInOut->getPointer();
9869   const int *srcArrPtr=srcArr->getConstPointer();
9870   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9871   int it=start;
9872   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9873     {
9874       if(it>=0 && it<nbOfTuples)
9875         {
9876           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9877             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9878           else
9879             {
9880               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9881               throw INTERP_KERNEL::Exception(oss.str().c_str());
9882             }
9883         }
9884       else
9885         {
9886           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9887           throw INTERP_KERNEL::Exception(oss.str().c_str());
9888         }
9889     }
9890 }
9891
9892 /*!
9893  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9894  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9895  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9896  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9897  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9898  * 
9899  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9900  */
9901 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9902 {
9903   checkFullyDefined();
9904   int mdim=getMeshDimension();
9905   int spaceDim=getSpaceDimension();
9906   if(mdim!=spaceDim)
9907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9908   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9909   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9910   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9911   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9912   ret->setCoords(getCoords());
9913   ret->allocateCells((int)partition.size());
9914   //
9915   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9916     {
9917       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9918       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9919       switch(mdim)
9920         {
9921         case 2:
9922           cell=tmp->buildUnionOf2DMesh();
9923           break;
9924         case 3:
9925           cell=tmp->buildUnionOf3DMesh();
9926           break;
9927         default:
9928           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9929         }
9930       
9931       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9932     }
9933   //
9934   ret->finishInsertingCells();
9935   return ret.retn();
9936 }
9937
9938 /*!
9939  * This method partitions \b this into contiguous zone.
9940  * This method only needs a well defined connectivity. Coordinates are not considered here.
9941  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9942  */
9943 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9944 {
9945   int nbOfCellsCur=getNumberOfCells();
9946   std::vector<DataArrayInt *> ret;
9947   if(nbOfCellsCur<=0)
9948     return ret;
9949   DataArrayInt *neigh=0,*neighI=0;
9950   computeNeighborsOfCells(neigh,neighI);
9951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9952   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9953   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9954   int seed=0;
9955   while(seed<nbOfCellsCur)
9956     {
9957       int nbOfPeelPerformed=0;
9958       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9959       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9960     }
9961   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9962     ret.push_back((*it).retn());
9963   return ret;
9964 }
9965
9966 /*!
9967  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9968  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9969  *
9970  * \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.
9971  * \return a newly allocated DataArrayInt to be managed by the caller.
9972  * \throw In case of \a code has not the right format (typically of size 3*n)
9973  */
9974 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9975 {
9976   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9977   std::size_t nb=code.size()/3;
9978   if(code.size()%3!=0)
9979     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9980   ret->alloc((int)nb,2);
9981   int *retPtr=ret->getPointer();
9982   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9983     {
9984       retPtr[0]=code[3*i+2];
9985       retPtr[1]=code[3*i+2]+code[3*i+1];
9986     }
9987   return ret.retn();
9988 }
9989
9990 /*!
9991  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9992  * All cells in \a this are expected to be linear 3D cells.
9993  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9994  * It leads to an increase to number of cells.
9995  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9996  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
9997  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9998  *
9999  * \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.
10000  *                      For all other cells, the splitting policy will be ignored.
10001  * \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. 
10002  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10003  *          an id of old cell producing it. The caller is to delete this array using
10004  *         decrRef() as it is no more needed.
10005  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10006  *
10007  * \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
10008  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10009  * 
10010  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10011  * \throw If \a this is not fully constituted with linear 3D cells.
10012  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10013  */
10014 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10015 {
10016   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
10017   checkConnectivityFullyDefined();
10018   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10019     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
10020   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
10021   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
10022   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
10023   int *retPt(ret->getPointer());
10024   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
10025   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
10026   const int *oldc(_nodal_connec->begin());
10027   const int *oldci(_nodal_connec_index->begin());
10028   const double *coords(_coords->begin());
10029   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
10030     {
10031       std::vector<int> a; std::vector<double> b;
10032       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
10033       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
10034       const int *aa(&a[0]);
10035       if(!b.empty())
10036         {
10037           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
10038             if(*it<0)
10039               *it=(-(*(it))-1+nbNodes);
10040           addPts->insertAtTheEnd(b.begin(),b.end());
10041           nbNodes+=(int)b.size()/3;
10042         }
10043       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
10044         newConn->insertAtTheEnd(aa,aa+4);
10045     }
10046   if(!addPts->empty())
10047     {
10048       addPts->rearrange(3);
10049       nbOfAdditionalPoints=addPts->getNumberOfTuples();
10050       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
10051       ret0->setCoords(addPts);
10052     }
10053   else
10054     {
10055       nbOfAdditionalPoints=0;
10056       ret0->setCoords(getCoords());
10057     }
10058   ret0->setNodalConnectivity(newConn);
10059   //
10060   ret->computeOffsets2();
10061   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
10062   return ret0.retn();
10063 }
10064
10065 /*!
10066  * 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). 
10067  *
10068  * \sa MEDCouplingUMesh::split2DCells
10069  */
10070 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
10071 {
10072   checkConnectivityFullyDefined();
10073   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
10074   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10075   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10076   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10077   int prevPosOfCi(ciPtr[0]);
10078   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10079     {
10080       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
10081       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
10082       for(int j=0;j<sz;j++)
10083         {
10084           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
10085           for(int k=0;k<sz2;k++)
10086             *cPtr++=subPtr[offset2+k];
10087           if(j!=sz-1)
10088             *cPtr++=oldConn[prevPosOfCi+j+2];
10089           deltaSz+=sz2;
10090         }
10091       prevPosOfCi=ciPtr[1];
10092       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10093     }
10094   if(c->end()!=cPtr)
10095     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
10096   _nodal_connec->decrRef();
10097   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
10098 }
10099
10100 int internalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
10101 {
10102   if(id!=-1)
10103     return id;
10104   else
10105     {
10106       int ret(nodesCnter++);
10107       double newPt[2];
10108       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
10109       addCoo.insertAtTheEnd(newPt,newPt+2);
10110       return ret;
10111     }
10112 }
10113
10114 /*!
10115  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
10116  *
10117  * \return  int - the number of new nodes created.
10118  * \sa MEDCouplingUMesh::split2DCells
10119  */
10120 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
10121 {
10122   checkCoherency();
10123   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
10124   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10125   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
10126   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10127   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
10128   const double *oldCoordsPtr(getCoords()->begin());
10129   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10130   int prevPosOfCi(ciPtr[0]);
10131   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10132     {
10133       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
10134       for(int j=0;j<sz;j++)
10135         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
10136       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
10137       for(int j=0;j<sz;j++)//loop over subedges of oldConn
10138         {
10139           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
10140           if(sz2==0)
10141             {
10142               if(j<sz-1)
10143                 cPtr[1]=oldConn[prevPosOfCi+2+j];
10144               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
10145               continue;
10146             }
10147           std::vector<INTERP_KERNEL::Node *> ns(3);
10148           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
10149           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
10150           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
10151           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
10152           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
10153             {
10154               cPtr[1]=subPtr[offset2+k];
10155               cPtr[deltaSz]=internalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
10156             }
10157           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
10158           if(j!=sz-1)
10159             { cPtr[1]=tmpEnd; }
10160           cPtr[deltaSz]=internalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
10161         }
10162       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
10163       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10164     }
10165   if(c->end()!=cPtr)
10166     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
10167   _nodal_connec->decrRef();
10168   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
10169   addCoo->rearrange(2);
10170   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
10171   setCoords(coo);
10172   return addCoo->getNumberOfTuples();
10173 }
10174
10175 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
10176                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
10177 {
10178   if(mesh)
10179     {
10180       mesh->incrRef();
10181       _nb_cell=mesh->getNumberOfCells();
10182     }
10183 }
10184
10185 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
10186 {
10187   if(_mesh)
10188     _mesh->decrRef();
10189   if(_own_cell)
10190     delete _cell;
10191 }
10192
10193 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
10194                                                                                                                                _own_cell(false),_cell_id(bg-1),
10195                                                                                                                                _nb_cell(end)
10196 {
10197   if(mesh)
10198     mesh->incrRef();
10199 }
10200
10201 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
10202 {
10203   _cell_id++;
10204   if(_cell_id<_nb_cell)
10205     {
10206       _cell->next();
10207       return _cell;
10208     }
10209   else
10210     return 0;
10211 }
10212
10213 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
10214 {
10215   if(_mesh)
10216     _mesh->incrRef();
10217 }
10218
10219 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
10220 {
10221   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
10222 }
10223
10224 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
10225 {
10226   if(_mesh)
10227     _mesh->decrRef();
10228 }
10229
10230 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
10231                                                                                                                                                                   _itc(itc),
10232                                                                                                                                                                   _bg(bg),_end(end)
10233 {
10234   if(_mesh)
10235     _mesh->incrRef();
10236 }
10237
10238 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
10239 {
10240   if(_mesh)
10241     _mesh->decrRef();
10242 }
10243
10244 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
10245 {
10246   return _type;
10247 }
10248
10249 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
10250 {
10251   return _end-_bg;
10252 }
10253
10254 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
10255 {
10256   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
10257 }
10258
10259 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
10260 {
10261   if(mesh)
10262     {
10263       mesh->incrRef();
10264       _nb_cell=mesh->getNumberOfCells();
10265     }
10266 }
10267
10268 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
10269 {
10270   if(_mesh)
10271     _mesh->decrRef();
10272   delete _cell;
10273 }
10274
10275 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
10276 {
10277   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
10278   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
10279   if(_cell_id<_nb_cell)
10280     {
10281       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
10282       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
10283       int startId=_cell_id;
10284       _cell_id+=nbOfElems;
10285       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
10286     }
10287   else
10288     return 0;
10289 }
10290
10291 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
10292 {
10293   if(mesh)
10294     {
10295       _conn=mesh->getNodalConnectivity()->getPointer();
10296       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
10297     }
10298 }
10299
10300 void MEDCouplingUMeshCell::next()
10301 {
10302   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10303     {
10304       _conn+=_conn_lgth;
10305       _conn_indx++;
10306     }
10307   _conn_lgth=_conn_indx[1]-_conn_indx[0];
10308 }
10309
10310 std::string MEDCouplingUMeshCell::repr() const
10311 {
10312   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10313     {
10314       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
10315       oss << " : ";
10316       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
10317       return oss.str();
10318     }
10319   else
10320     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
10321 }
10322
10323 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
10324 {
10325   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10326     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
10327   else
10328     return INTERP_KERNEL::NORM_ERROR;
10329 }
10330
10331 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
10332 {
10333   lgth=_conn_lgth;
10334   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10335     return _conn;
10336   else
10337     return 0;
10338 }