Salome HOME
getWarpField(): documentation
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2015  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 "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
30 #include "BBTree.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
44
45 #include <sstream>
46 #include <fstream>
47 #include <numeric>
48 #include <cstring>
49 #include <limits>
50 #include <list>
51
52 using namespace MEDCoupling;
53
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
55
56 /// @cond INTERNAL
57 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 };
58 /// @endcond
59
60 MEDCouplingUMesh *MEDCouplingUMesh::New()
61 {
62   return new MEDCouplingUMesh;
63 }
64
65 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
66 {
67   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
68   ret->setName(meshName);
69   ret->setMeshDimension(meshDim);
70   return ret;
71 }
72
73 /*!
74  * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
75  * between \a this and the new mesh.
76  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
77  *          delete this mesh using decrRef() as it is no more needed. 
78  */
79 MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const
80 {
81   return clone(true);
82 }
83
84
85 /*!
86  * Returns a new MEDCouplingUMesh which is a copy of \a this one.
87  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
88  * this mesh are shared by the new mesh.
89  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
90  *          delete this mesh using decrRef() as it is no more needed. 
91  */
92 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
93 {
94   return new MEDCouplingUMesh(*this,recDeepCpy);
95 }
96
97 /*!
98  * This method behaves mostly like MEDCouplingUMesh::deepCopy method, except that only nodal connectivity arrays are deeply copied.
99  * The coordinates are shared between \a this and the returned instance.
100  * 
101  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
102  * \sa MEDCouplingUMesh::deepCopy
103  */
104 MEDCouplingUMesh *MEDCouplingUMesh::deepCopyConnectivityOnly() const
105 {
106   checkConnectivityFullyDefined();
107   MCAuto<MEDCouplingUMesh> ret=clone(false);
108   MCAuto<DataArrayInt> c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy());
109   ret->setConnectivity(c,ci);
110   return ret.retn();
111 }
112
113 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
114 {
115   if(!other)
116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
117   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
118   if(!otherC)
119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
120   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
121   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
122 }
123
124 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
125 {
126   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
127   return ret;
128 }
129
130 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
131 {
132   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
133   ret.push_back(_nodal_connec);
134   ret.push_back(_nodal_connec_index);
135   return ret;
136 }
137
138 void MEDCouplingUMesh::updateTime() const
139 {
140   MEDCouplingPointSet::updateTime();
141   if(_nodal_connec)
142     {
143       updateTimeWith(*_nodal_connec);
144     }
145   if(_nodal_connec_index)
146     {
147       updateTimeWith(*_nodal_connec_index);
148     }
149 }
150
151 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
152 {
153 }
154
155 /*!
156  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
157  * then \a this mesh is most probably is writable, exchangeable and available for most
158  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
159  * this method to check that all is in order with \a this mesh.
160  *  \throw If the mesh dimension is not set.
161  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
162  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
163  *  \throw If the connectivity data array has more than one component.
164  *  \throw If the connectivity data array has a named component.
165  *  \throw If the connectivity index data array has more than one component.
166  *  \throw If the connectivity index data array has a named component.
167  */
168 void MEDCouplingUMesh::checkConsistencyLight() const
169 {
170   if(_mesh_dim<-1)
171     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
172   if(_mesh_dim!=-1)
173     MEDCouplingPointSet::checkConsistencyLight();
174   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
175     {
176       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
177         {
178           std::ostringstream message;
179           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
180           throw INTERP_KERNEL::Exception(message.str().c_str());
181         }
182     }
183   if(_nodal_connec)
184     {
185       if(_nodal_connec->getNumberOfComponents()!=1)
186         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
187       if(_nodal_connec->getInfoOnComponent(0)!="")
188         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
189     }
190   else
191     if(_mesh_dim!=-1)
192       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
193   if(_nodal_connec_index)
194     {
195       if(_nodal_connec_index->getNumberOfComponents()!=1)
196         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
197       if(_nodal_connec_index->getInfoOnComponent(0)!="")
198         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
199     }
200   else
201     if(_mesh_dim!=-1)
202       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
203 }
204
205 /*!
206  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
207  * then \a this mesh is most probably is writable, exchangeable and available for all
208  * algorithms. <br> In addition to the checks performed by checkConsistencyLight(), this
209  * method thoroughly checks the nodal connectivity.
210  *  \param [in] eps - a not used parameter.
211  *  \throw If the mesh dimension is not set.
212  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
213  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
214  *  \throw If the connectivity data array has more than one component.
215  *  \throw If the connectivity data array has a named component.
216  *  \throw If the connectivity index data array has more than one component.
217  *  \throw If the connectivity index data array has a named component.
218  *  \throw If number of nodes defining an element does not correspond to the type of element.
219  *  \throw If the nodal connectivity includes an invalid node id.
220  */
221 void MEDCouplingUMesh::checkConsistency(double eps) const
222 {
223   checkConsistencyLight();
224   if(_mesh_dim==-1)
225     return ;
226   int meshDim=getMeshDimension();
227   int nbOfNodes=getNumberOfNodes();
228   int nbOfCells=getNumberOfCells();
229   const int *ptr=_nodal_connec->getConstPointer();
230   const int *ptrI=_nodal_connec_index->getConstPointer();
231   for(int i=0;i<nbOfCells;i++)
232     {
233       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
234       if((int)cm.getDimension()!=meshDim)
235         {
236           std::ostringstream oss;
237           oss << "MEDCouplingUMesh::checkConsistency : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
238           throw INTERP_KERNEL::Exception(oss.str().c_str());
239         }
240       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
241       if(!cm.isDynamic())
242         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
243           {
244             std::ostringstream oss;
245             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
246             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
247             throw INTERP_KERNEL::Exception(oss.str().c_str());
248           }
249       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
250         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
251           {
252             std::ostringstream oss;
253             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
254             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
255             throw INTERP_KERNEL::Exception(oss.str().c_str());
256           }
257       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
258         {
259           int nodeId=*w;
260           if(nodeId>=0)
261             {
262               if(nodeId>=nbOfNodes)
263                 {
264                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
265                   throw INTERP_KERNEL::Exception(oss.str().c_str());
266                 }
267             }
268           else if(nodeId<-1)
269             {
270               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
271               throw INTERP_KERNEL::Exception(oss.str().c_str());
272             }
273           else
274             {
275               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
276                 {
277                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
278                   throw INTERP_KERNEL::Exception(oss.str().c_str());
279                 }
280             }
281         }
282     }
283 }
284
285 /*!
286  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
287  * elements contained in the mesh. For more info on the mesh dimension see
288  * \ref MEDCouplingUMeshPage.
289  *  \param [in] meshDim - a new mesh dimension.
290  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
291  */
292 void MEDCouplingUMesh::setMeshDimension(int meshDim)
293 {
294   if(meshDim<-1 || meshDim>3)
295     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
296   _mesh_dim=meshDim;
297   declareAsNew();
298 }
299
300 /*!
301  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
302  * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
303  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
304  *
305  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
306  *
307  *  \if ENABLE_EXAMPLES
308  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
309  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
310  *  \endif
311  */
312 void MEDCouplingUMesh::allocateCells(int nbOfCells)
313 {
314   if(nbOfCells<0)
315     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
316   if(_nodal_connec_index)
317     {
318       _nodal_connec_index->decrRef();
319     }
320   if(_nodal_connec)
321     {
322       _nodal_connec->decrRef();
323     }
324   _nodal_connec_index=DataArrayInt::New();
325   _nodal_connec_index->reserve(nbOfCells+1);
326   _nodal_connec_index->pushBackSilent(0);
327   _nodal_connec=DataArrayInt::New();
328   _nodal_connec->reserve(2*nbOfCells);
329   _types.clear();
330   declareAsNew();
331 }
332
333 /*!
334  * Appends a cell to the connectivity array. For deeper understanding what is
335  * happening see \ref MEDCouplingUMeshNodalConnectivity.
336  *  \param [in] type - type of cell to add.
337  *  \param [in] size - number of nodes constituting this cell.
338  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
339  * 
340  *  \if ENABLE_EXAMPLES
341  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
342  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
343  *  \endif
344  */
345 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
346 {
347   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
348   if(_nodal_connec_index==0)
349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
350   if((int)cm.getDimension()==_mesh_dim)
351     {
352       if(!cm.isDynamic())
353         if(size!=(int)cm.getNumberOfNodes())
354           {
355             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
356             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
357             throw INTERP_KERNEL::Exception(oss.str().c_str());
358           }
359       int idx=_nodal_connec_index->back();
360       int val=idx+size+1;
361       _nodal_connec_index->pushBackSilent(val);
362       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
363       _types.insert(type);
364     }
365   else
366     {
367       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
368       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
369       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
370       throw INTERP_KERNEL::Exception(oss.str().c_str());
371     }
372 }
373
374 /*!
375  * Compacts data arrays to release unused memory. This method is to be called after
376  * finishing cell insertion using \a this->insertNextCell().
377  * 
378  *  \if ENABLE_EXAMPLES
379  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
380  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
381  *  \endif
382  */
383 void MEDCouplingUMesh::finishInsertingCells()
384 {
385   _nodal_connec->pack();
386   _nodal_connec_index->pack();
387   _nodal_connec->declareAsNew();
388   _nodal_connec_index->declareAsNew();
389   updateTime();
390 }
391
392 /*!
393  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
394  * Useful for python users.
395  */
396 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
397 {
398   return new MEDCouplingUMeshCellIterator(this);
399 }
400
401 /*!
402  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
403  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
404  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
405  * Useful for python users.
406  */
407 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
408 {
409   if(!checkConsecutiveCellTypes())
410     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
411   return new MEDCouplingUMeshCellByTypeEntry(this);
412 }
413
414 /*!
415  * Returns a set of all cell types available in \a this mesh.
416  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
417  * \warning this method does not throw any exception even if \a this is not defined.
418  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
419  */
420 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
421 {
422   return _types;
423 }
424
425 /*!
426  * This method returns the sorted list of geometric types in \a this.
427  * 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
428  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
429  *
430  * \throw if connectivity in \a this is not correctly defined.
431  *  
432  * \sa MEDCouplingMesh::getAllGeoTypes
433  */
434 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
435 {
436   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
437   checkConnectivityFullyDefined();
438   int nbOfCells(getNumberOfCells());
439   if(nbOfCells==0)
440     return ret;
441   if(getNodalConnectivityArrayLen()<1)
442     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
443   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
444   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
445   for(int i=1;i<nbOfCells;i++,ci++)
446     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
447       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
448   return ret;
449 }
450
451 /*!
452  * This method is a method that compares \a this and \a other.
453  * This method compares \b all attributes, even names and component names.
454  */
455 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
456 {
457   if(!other)
458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
459   std::ostringstream oss; oss.precision(15);
460   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
461   if(!otherC)
462     {
463       reason="mesh given in input is not castable in MEDCouplingUMesh !";
464       return false;
465     }
466   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
467     return false;
468   if(_mesh_dim!=otherC->_mesh_dim)
469     {
470       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
471       reason=oss.str();
472       return false;
473     }
474   if(_types!=otherC->_types)
475     {
476       oss << "umesh geometric type mismatch :\nThis geometric types are :";
477       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
478         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
479       oss << "\nOther geometric types are :";
480       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
481         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
482       reason=oss.str();
483       return false;
484     }
485   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
486     if(_nodal_connec==0 || otherC->_nodal_connec==0)
487       {
488         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
489         return false;
490       }
491   if(_nodal_connec!=otherC->_nodal_connec)
492     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
493       {
494         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
495         return false;
496       }
497   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
498     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
499       {
500         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
501         return false;
502       }
503   if(_nodal_connec_index!=otherC->_nodal_connec_index)
504     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
505       {
506         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
507         return false;
508       }
509   return true;
510 }
511
512 /*!
513  * Checks if data arrays of this mesh (node coordinates, nodal
514  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
515  * not considered.
516  *  \param [in] other - the mesh to compare with.
517  *  \param [in] prec - precision value used to compare node coordinates.
518  *  \return bool - \a true if the two meshes are same.
519  */
520 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
521 {
522   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
523   if(!otherC)
524     return false;
525   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
526     return false;
527   if(_mesh_dim!=otherC->_mesh_dim)
528     return false;
529   if(_types!=otherC->_types)
530     return false;
531   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
532     if(_nodal_connec==0 || otherC->_nodal_connec==0)
533       return false;
534   if(_nodal_connec!=otherC->_nodal_connec)
535     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
536       return false;
537   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
538     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
539       return false;
540   if(_nodal_connec_index!=otherC->_nodal_connec_index)
541     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
542       return false;
543   return true;
544 }
545
546 /*!
547  * Checks if \a this and \a other meshes are geometrically equivalent with high
548  * probability, else an exception is thrown. The meshes are considered equivalent if
549  * (1) meshes contain the same number of nodes and the same number of elements of the
550  * same types (2) three cells of the two meshes (first, last and middle) are based
551  * on coincident nodes (with a specified precision).
552  *  \param [in] other - the mesh to compare with.
553  *  \param [in] prec - the precision used to compare nodes of the two meshes.
554  *  \throw If the two meshes do not match.
555  */
556 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
557 {
558   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
559   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
560   if(!otherC)
561     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
562 }
563
564 /*!
565  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
566  * cells each node belongs to.
567  * \warning For speed reasons, this method does not check if node ids in the nodal
568  *          connectivity correspond to the size of node coordinates array.
569  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
570  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
571  *        dividing cell ids in \a revNodal into groups each referring to one
572  *        node. Its every element (except the last one) is an index pointing to the
573  *         first id of a group of cells. For example cells sharing the node #1 are 
574  *        described by following range of indices: 
575  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
576  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
577  *        Number of cells sharing the *i*-th node is
578  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
579  * \throw If the coordinates array is not set.
580  * \throw If the nodal connectivity of cells is not defined.
581  * 
582  * \if ENABLE_EXAMPLES
583  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
584  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
585  * \endif
586  */
587 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
588 {
589   checkFullyDefined();
590   int nbOfNodes=getNumberOfNodes();
591   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
592   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
593   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
594   const int *conn=_nodal_connec->getConstPointer();
595   const int *connIndex=_nodal_connec_index->getConstPointer();
596   int nbOfCells=getNumberOfCells();
597   int nbOfEltsInRevNodal=0;
598   for(int eltId=0;eltId<nbOfCells;eltId++)
599     {
600       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
601       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
602       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
603         if(*iter>=0)//for polyhedrons
604           {
605             nbOfEltsInRevNodal++;
606             revNodalIndxPtr[(*iter)+1]++;
607           }
608     }
609   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
610   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
611   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
612   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
613   for(int eltId=0;eltId<nbOfCells;eltId++)
614     {
615       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
616       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
617       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
618         if(*iter>=0)//for polyhedrons
619           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
620     }
621 }
622
623 /// @cond INTERNAL
624
625 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
626 {
627   return id;
628 }
629
630 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
631 {
632   if(!compute)
633     return id+1;
634   else
635     {
636       if(cm.getOrientationStatus(nb,conn1,conn2))
637         return id+1;
638       else
639         return -(id+1);
640     }
641 }
642
643 class MinusOneSonsGenerator
644 {
645 public:
646   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
647   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
648   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
649   static const int DELTA=1;
650 private:
651   const INTERP_KERNEL::CellModel& _cm;
652 };
653
654 class MinusOneSonsGeneratorBiQuadratic
655 {
656 public:
657   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
658   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
659   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
660   static const int DELTA=1;
661 private:
662   const INTERP_KERNEL::CellModel& _cm;
663 };
664
665 class MinusTwoSonsGenerator
666 {
667 public:
668   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
669   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
670   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
671   static const int DELTA=2;
672 private:
673   const INTERP_KERNEL::CellModel& _cm;
674 };
675
676 /// @endcond
677
678 /*!
679  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
680  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
681  * describing correspondence between cells of \a this and the result meshes are
682  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
683  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
684  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
685  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
686  * \warning For speed reasons, this method does not check if node ids in the nodal
687  *          connectivity correspond to the size of node coordinates array.
688  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
689  *          to write this mesh to the MED file, its cells must be sorted using
690  *          sortCellsInMEDFileFrmt().
691  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
692  *         each cell of \a this mesh.
693  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
694  *        dividing cell ids in \a desc into groups each referring to one
695  *        cell of \a this mesh. Its every element (except the last one) is an index
696  *        pointing to the first id of a group of cells. For example cells of the
697  *        result mesh bounding the cell #1 of \a this mesh are described by following
698  *        range of indices:
699  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
700  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
701  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
702  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
703  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
704  *         by each cell of the result mesh.
705  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
706  *        in the result mesh,
707  *        dividing cell ids in \a revDesc into groups each referring to one
708  *        cell of the result mesh the same way as \a descIndx divides \a desc.
709  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
710  *        delete this mesh using decrRef() as it is no more needed.
711  *  \throw If the coordinates array is not set.
712  *  \throw If the nodal connectivity of cells is node defined.
713  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
714  *         revDescIndx == NULL.
715  * 
716  *  \if ENABLE_EXAMPLES
717  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
718  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
719  *  \endif
720  * \sa buildDescendingConnectivity2()
721  */
722 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
723 {
724   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
725 }
726
727 /*!
728  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
729  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
730  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
731  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
732  * \sa MEDCouplingUMesh::buildDescendingConnectivity
733  */
734 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
735 {
736   checkFullyDefined();
737   if(getMeshDimension()!=3)
738     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
739   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
740 }
741
742 /*!
743  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
744  * this->getMeshDimension(), that bound cells of \a this mesh. In
745  * addition arrays describing correspondence between cells of \a this and the result
746  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
747  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
748  *  mesh. This method differs from buildDescendingConnectivity() in that apart
749  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
750  * result meshes. So a positive id means that order of nodes in corresponding cells
751  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
752  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
753  * i.e. cell ids are one-based.
754  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
755  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
756  * \warning For speed reasons, this method does not check if node ids in the nodal
757  *          connectivity correspond to the size of node coordinates array.
758  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
759  *          to write this mesh to the MED file, its cells must be sorted using
760  *          sortCellsInMEDFileFrmt().
761  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
762  *         each cell of \a this mesh.
763  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
764  *        dividing cell ids in \a desc into groups each referring to one
765  *        cell of \a this mesh. Its every element (except the last one) is an index
766  *        pointing to the first id of a group of cells. For example cells of the
767  *        result mesh bounding the cell #1 of \a this mesh are described by following
768  *        range of indices:
769  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
770  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
771  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
772  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
773  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
774  *         by each cell of the result mesh.
775  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
776  *        in the result mesh,
777  *        dividing cell ids in \a revDesc into groups each referring to one
778  *        cell of the result mesh the same way as \a descIndx divides \a desc.
779  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
780  *        shares the node coordinates array with \a this mesh. The caller is to
781  *        delete this mesh using decrRef() as it is no more needed.
782  *  \throw If the coordinates array is not set.
783  *  \throw If the nodal connectivity of cells is node defined.
784  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
785  *         revDescIndx == NULL.
786  * 
787  *  \if ENABLE_EXAMPLES
788  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
789  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
790  *  \endif
791  * \sa buildDescendingConnectivity()
792  */
793 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
794 {
795   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
796 }
797
798 /*!
799  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
800  * For speed reasons no check of this will be done. This method calls
801  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
802  * This method lists cell by cell in \b this which are its neighbors. To compute the result
803  * only connectivities are considered.
804  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
805  * The format of return is hence \ref numbering-indirect.
806  *
807  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
808  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
809  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
810  * is equal to the last values in \b neighborsIndx.
811  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
812  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
813  */
814 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
815 {
816   MCAuto<DataArrayInt> desc=DataArrayInt::New();
817   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
818   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
819   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
820   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
821   meshDM1=0;
822   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
823 }
824
825 /*!
826  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
827  * of MEDCouplingUMesh::computeNeighborsOfCells.
828  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
829  * typically the case to extract a set a neighbours,
830  * excluding a set of meshdim-1 cells in input descending connectivity.
831  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
832  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
833  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
834  * are considered.
835  * The neighbor cells of cell having id 'cellId' 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 (\ref numbering-indirect).
839  * \param [in] revDesc reverse descending connectivity array.
840  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
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)
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   MCAuto<DataArrayInt> out0=DataArrayInt::New();
857   MCAuto<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 /*!
876  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
877  * For speed reasons no check of this will be done. This method calls
878  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
879  * This method lists node by node in \b this which are its neighbors. To compute the result
880  * only connectivities are considered.
881  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
882  *
883  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
884  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
885  * parameter allows to select the right part in this array (\ref numbering-indirect).
886  * The number of tuples is equal to the last values in \b neighborsIndx.
887  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
888  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
889  */
890 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
891 {
892   checkFullyDefined();
893   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
894   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
895   MCAuto<MEDCouplingUMesh> mesh1D;
896   switch(mdim)
897   {
898     case 3:
899       {
900         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
901         break;
902       }
903     case 2:
904       {
905         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
906         break;
907       }
908     case 1:
909       {
910         mesh1D=const_cast<MEDCouplingUMesh *>(this);
911         mesh1D->incrRef();
912         break;
913       }
914     default:
915       {
916         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
917       }
918   }
919   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
920   mesh1D->getReverseNodalConnectivity(desc,descIndx);
921   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
922   ret0->alloc(desc->getNumberOfTuples(),1);
923   int *r0Pt(ret0->getPointer());
924   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
925   for(int i=0;i<nbNodes;i++,rni++)
926     {
927       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
928         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
929     }
930   neighbors=ret0.retn();
931   neighborsIdx=descIndx.retn();
932 }
933
934 /// @cond INTERNAL
935
936 /*!
937  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
938  * For speed reasons no check of this will be done.
939  */
940 template<class SonsGenerator>
941 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
942 {
943   if(!desc || !descIndx || !revDesc || !revDescIndx)
944     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
945   checkConnectivityFullyDefined();
946   int nbOfCells=getNumberOfCells();
947   int nbOfNodes=getNumberOfNodes();
948   MCAuto<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
949   int *revNodalIndxPtr=revNodalIndx->getPointer();
950   const int *conn=_nodal_connec->getConstPointer();
951   const int *connIndex=_nodal_connec_index->getConstPointer();
952   std::string name="Mesh constituent of "; name+=getName();
953   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
954   ret->setCoords(getCoords());
955   ret->allocateCells(2*nbOfCells);
956   descIndx->alloc(nbOfCells+1,1);
957   MCAuto<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
958   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
959   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
960     {
961       int pos=connIndex[eltId];
962       int posP1=connIndex[eltId+1];
963       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
964       SonsGenerator sg(cm);
965       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
966       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
967       for(unsigned i=0;i<nbOfSons;i++)
968         {
969           INTERP_KERNEL::NormalizedCellType cmsId;
970           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
971           for(unsigned k=0;k<nbOfNodesSon;k++)
972             if(tmp[k]>=0)
973               revNodalIndxPtr[tmp[k]+1]++;
974           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
975           revDesc2->pushBackSilent(eltId);
976         }
977       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
978     }
979   int nbOfCellsM1=ret->getNumberOfCells();
980   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
981   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
982   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
983   int *revNodalPtr=revNodal->getPointer();
984   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
985   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
986   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
987     {
988       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
989       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
990       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
991         if(*iter>=0)//for polyhedrons
992           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
993     }
994   //
995   DataArrayInt *commonCells=0,*commonCellsI=0;
996   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
997   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
998   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
999   int newNbOfCellsM1=-1;
1000   MCAuto<DataArrayInt> o2nM1=DataArrayInt::ConvertIndexArrayToO2N(nbOfCellsM1,commonCells->begin(),
1001                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1002   std::vector<bool> isImpacted(nbOfCellsM1,false);
1003   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1004     for(int work2=work[0];work2!=work[1];work2++)
1005       isImpacted[commonCellsPtr[work2]]=true;
1006   const int *o2nM1Ptr=o2nM1->getConstPointer();
1007   MCAuto<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1008   const int *n2oM1Ptr=n2oM1->getConstPointer();
1009   MCAuto<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1010   ret2->copyTinyInfoFrom(this);
1011   desc->alloc(descIndx->back(),1);
1012   int *descPtr=desc->getPointer();
1013   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1014   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1015     {
1016       if(!isImpacted[i])
1017         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1018       else
1019         {
1020           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1021             {
1022               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1023               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1024             }
1025           else
1026             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1027         }
1028     }
1029   revDesc->reserve(newNbOfCellsM1);
1030   revDescIndx->alloc(newNbOfCellsM1+1,1);
1031   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1032   const int *revDesc2Ptr=revDesc2->getConstPointer();
1033   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1034     {
1035       int oldCellIdM1=n2oM1Ptr[i];
1036       if(!isImpacted[oldCellIdM1])
1037         {
1038           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1039           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1040         }
1041       else
1042         {
1043           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1044             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1045           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1046           commonCellsIPtr++;
1047         }
1048     }
1049   //
1050   return ret2.retn();
1051 }
1052
1053 struct MEDCouplingAccVisit
1054 {
1055   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1056   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1057   int _new_nb_of_nodes;
1058 };
1059
1060 /// @endcond
1061
1062 /*!
1063  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1064  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1065  * array of cell ids. Pay attention that after conversion all algorithms work slower
1066  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1067  * conversion due presence of invalid ids in the array of cells to convert, as a
1068  * result \a this mesh contains some already converted elements. In this case the 2D
1069  * mesh remains valid but 3D mesh becomes \b inconsistent!
1070  *  \warning This method can significantly modify the order of geometric types in \a this,
1071  *          hence, to write this mesh to the MED file, its cells must be sorted using
1072  *          sortCellsInMEDFileFrmt().
1073  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1074  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1075  *         cellIdsToConvertBg.
1076  *  \throw If the coordinates array is not set.
1077  *  \throw If the nodal connectivity of cells is node defined.
1078  *  \throw If dimension of \a this mesh is not either 2 or 3.
1079  *
1080  *  \if ENABLE_EXAMPLES
1081  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1082  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1083  *  \endif
1084  */
1085 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1086 {
1087   checkFullyDefined();
1088   int dim=getMeshDimension();
1089   if(dim<2 || dim>3)
1090     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1091   int nbOfCells(getNumberOfCells());
1092   if(dim==2)
1093     {
1094       const int *connIndex=_nodal_connec_index->getConstPointer();
1095       int *conn=_nodal_connec->getPointer();
1096       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1097         {
1098           if(*iter>=0 && *iter<nbOfCells)
1099             {
1100               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1101               if(!cm.isQuadratic())
1102                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1103               else
1104                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1105             }
1106           else
1107             {
1108               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1109               oss << " in range [0," << nbOfCells << ") !";
1110               throw INTERP_KERNEL::Exception(oss.str().c_str());
1111             }
1112         }
1113     }
1114   else
1115     {
1116       int *connIndex(_nodal_connec_index->getPointer());
1117       const int *connOld(_nodal_connec->getConstPointer());
1118       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1119       std::vector<bool> toBeDone(nbOfCells,false);
1120       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1121         {
1122           if(*iter>=0 && *iter<nbOfCells)
1123             toBeDone[*iter]=true;
1124           else
1125             {
1126               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1127               oss << " in range [0," << nbOfCells << ") !";
1128               throw INTERP_KERNEL::Exception(oss.str().c_str());
1129             }
1130         }
1131       for(int cellId=0;cellId<nbOfCells;cellId++)
1132         {
1133           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1134           int lgthOld(posP1-pos-1);
1135           if(toBeDone[cellId])
1136             {
1137               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1138               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1139               int *tmp(new int[nbOfFaces*lgthOld+1]);
1140               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1141               for(unsigned j=0;j<nbOfFaces;j++)
1142                 {
1143                   INTERP_KERNEL::NormalizedCellType type;
1144                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1145                   work+=offset;
1146                   *work++=-1;
1147                 }
1148               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1149               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1150               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1151               delete [] tmp;
1152             }
1153           else
1154             {
1155               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1156               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1157             }
1158         }
1159       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1160     }
1161   computeTypes();
1162 }
1163
1164 /*!
1165  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1166  * polyhedrons (if \a this is a 3D mesh).
1167  *  \warning As this method is purely for user-friendliness and no optimization is
1168  *          done to avoid construction of a useless vector, this method can be costly
1169  *          in memory.
1170  *  \throw If the coordinates array is not set.
1171  *  \throw If the nodal connectivity of cells is node defined.
1172  *  \throw If dimension of \a this mesh is not either 2 or 3.
1173  */
1174 void MEDCouplingUMesh::convertAllToPoly()
1175 {
1176   int nbOfCells=getNumberOfCells();
1177   std::vector<int> cellIds(nbOfCells);
1178   for(int i=0;i<nbOfCells;i++)
1179     cellIds[i]=i;
1180   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1181 }
1182
1183 /*!
1184  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1185  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1186  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1187  * base facet of the volume and the second half of nodes describes an opposite facet
1188  * having the same number of nodes as the base one. This method converts such
1189  * connectivity to a valid polyhedral format where connectivity of each facet is
1190  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1191  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1192  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1193  * a correct orientation of the first facet of a polyhedron, else orientation of a
1194  * corrected cell is reverse.<br>
1195  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1196  * it releases the user from boring description of polyhedra connectivity in the valid
1197  * format.
1198  *  \throw If \a this->getMeshDimension() != 3.
1199  *  \throw If \a this->getSpaceDimension() != 3.
1200  *  \throw If the nodal connectivity of cells is not defined.
1201  *  \throw If the coordinates array is not set.
1202  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1203  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1204  *
1205  *  \if ENABLE_EXAMPLES
1206  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1207  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1208  *  \endif
1209  */
1210 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1211 {
1212   checkFullyDefined();
1213   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1214     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1215   int nbOfCells=getNumberOfCells();
1216   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1217   newCi->alloc(nbOfCells+1,1);
1218   int *newci=newCi->getPointer();
1219   const int *ci=_nodal_connec_index->getConstPointer();
1220   const int *c=_nodal_connec->getConstPointer();
1221   newci[0]=0;
1222   for(int i=0;i<nbOfCells;i++)
1223     {
1224       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1225       if(type==INTERP_KERNEL::NORM_POLYHED)
1226         {
1227           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1228             {
1229               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1230               throw INTERP_KERNEL::Exception(oss.str().c_str());
1231             }
1232           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1233           if(n2%2!=0)
1234             {
1235               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 !";
1236               throw INTERP_KERNEL::Exception(oss.str().c_str());
1237             }
1238           int n1=(int)(n2/2);
1239           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)
1240         }
1241       else
1242         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1243     }
1244   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1245   newC->alloc(newci[nbOfCells],1);
1246   int *newc=newC->getPointer();
1247   for(int i=0;i<nbOfCells;i++)
1248     {
1249       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1250       if(type==INTERP_KERNEL::NORM_POLYHED)
1251         {
1252           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1253           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1254           *newc++=-1;
1255           for(std::size_t j=0;j<n1;j++)
1256             {
1257               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1258               newc[n1+5*j]=-1;
1259               newc[n1+5*j+1]=c[ci[i]+1+j];
1260               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1261               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1262               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1263             }
1264           newc+=n1*6;
1265         }
1266       else
1267         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1268     }
1269   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1270   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1271 }
1272
1273
1274 /*!
1275  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1276  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1277  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1278  *          to write this mesh to the MED file, its cells must be sorted using
1279  *          sortCellsInMEDFileFrmt().
1280  * \return \c true if at least one cell has been converted, \c false else. In the
1281  *         last case the nodal connectivity remains unchanged.
1282  * \throw If the coordinates array is not set.
1283  * \throw If the nodal connectivity of cells is not defined.
1284  * \throw If \a this->getMeshDimension() < 0.
1285  */
1286 bool MEDCouplingUMesh::unPolyze()
1287 {
1288   checkFullyDefined();
1289   int mdim=getMeshDimension();
1290   if(mdim<0)
1291     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1292   if(mdim<=1)
1293     return false;
1294   int nbOfCells=getNumberOfCells();
1295   if(nbOfCells<1)
1296     return false;
1297   int initMeshLgth=getNodalConnectivityArrayLen();
1298   int *conn=_nodal_connec->getPointer();
1299   int *index=_nodal_connec_index->getPointer();
1300   int posOfCurCell=0;
1301   int newPos=0;
1302   int lgthOfCurCell;
1303   bool ret=false;
1304   for(int i=0;i<nbOfCells;i++)
1305     {
1306       lgthOfCurCell=index[i+1]-posOfCurCell;
1307       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1308       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1309       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1310       int newLgth;
1311       if(cm.isDynamic())
1312         {
1313           switch(cm.getDimension())
1314           {
1315             case 2:
1316               {
1317                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1318                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1319                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1320                 break;
1321               }
1322             case 3:
1323               {
1324                 int nbOfFaces,lgthOfPolyhConn;
1325                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1326                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1327                 break;
1328               }
1329             case 1:
1330               {
1331                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1332                 break;
1333               }
1334           }
1335           ret=ret || (newType!=type);
1336           conn[newPos]=newType;
1337           newPos+=newLgth+1;
1338           posOfCurCell=index[i+1];
1339           index[i+1]=newPos;
1340         }
1341       else
1342         {
1343           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1344           newPos+=lgthOfCurCell;
1345           posOfCurCell+=lgthOfCurCell;
1346           index[i+1]=newPos;
1347         }
1348     }
1349   if(newPos!=initMeshLgth)
1350     _nodal_connec->reAlloc(newPos);
1351   if(ret)
1352     computeTypes();
1353   return ret;
1354 }
1355
1356 /*!
1357  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1358  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1359  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1360  *
1361  * \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 
1362  *             precision.
1363  */
1364 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1365 {
1366   checkFullyDefined();
1367   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1369   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1370   coords->recenterForMaxPrecision(eps);
1371   //
1372   int nbOfCells=getNumberOfCells();
1373   const int *conn=_nodal_connec->getConstPointer();
1374   const int *index=_nodal_connec_index->getConstPointer();
1375   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1376   connINew->alloc(nbOfCells+1,1);
1377   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1378   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1379   bool changed=false;
1380   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1381     {
1382       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1383         {
1384           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1385           changed=true;
1386         }
1387       else
1388         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1389       *connINewPtr=connNew->getNumberOfTuples();
1390     }
1391   if(changed)
1392     setConnectivity(connNew,connINew,false);
1393 }
1394
1395 /*!
1396  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1397  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1398  * the format of the returned DataArrayInt instance.
1399  * 
1400  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1401  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1402  */
1403 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1404 {
1405   checkConnectivityFullyDefined();
1406   int nbOfCells=getNumberOfCells();
1407   const int *connIndex=_nodal_connec_index->getConstPointer();
1408   const int *conn=_nodal_connec->getConstPointer();
1409   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1410   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1411   std::vector<bool> retS(maxElt,false);
1412   for(int i=0;i<nbOfCells;i++)
1413     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1414       if(conn[j]>=0)
1415         retS[conn[j]]=true;
1416   int sz=0;
1417   for(int i=0;i<maxElt;i++)
1418     if(retS[i])
1419       sz++;
1420   DataArrayInt *ret=DataArrayInt::New();
1421   ret->alloc(sz,1);
1422   int *retPtr=ret->getPointer();
1423   for(int i=0;i<maxElt;i++)
1424     if(retS[i])
1425       *retPtr++=i;
1426   return ret;
1427 }
1428
1429 /*!
1430  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1431  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1432  */
1433 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1434 {
1435   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1436   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1437   for(int i=0;i<nbOfCells;i++)
1438     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1439       if(conn[j]>=0)
1440         {
1441           if(conn[j]<nbOfNodes)
1442             nodeIdsInUse[conn[j]]=true;
1443           else
1444             {
1445               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1446               throw INTERP_KERNEL::Exception(oss.str().c_str());
1447             }
1448         }
1449 }
1450
1451 /*!
1452  * Finds nodes not used in any cell and returns an array giving a new id to every node
1453  * by excluding the unused nodes, for which the array holds -1. The result array is
1454  * a mapping in "Old to New" mode. 
1455  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1456  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1457  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1458  *          if the node is unused or a new id else. The caller is to delete this
1459  *          array using decrRef() as it is no more needed.  
1460  *  \throw If the coordinates array is not set.
1461  *  \throw If the nodal connectivity of cells is not defined.
1462  *  \throw If the nodal connectivity includes an invalid id.
1463  *
1464  *  \if ENABLE_EXAMPLES
1465  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1466  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1467  *  \endif
1468  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1469  */
1470 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1471 {
1472   nbrOfNodesInUse=-1;
1473   int nbOfNodes(getNumberOfNodes());
1474   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1475   ret->alloc(nbOfNodes,1);
1476   int *traducer=ret->getPointer();
1477   std::fill(traducer,traducer+nbOfNodes,-1);
1478   int nbOfCells=getNumberOfCells();
1479   const int *connIndex=_nodal_connec_index->getConstPointer();
1480   const int *conn=_nodal_connec->getConstPointer();
1481   for(int i=0;i<nbOfCells;i++)
1482     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1483       if(conn[j]>=0)
1484         {
1485           if(conn[j]<nbOfNodes)
1486             traducer[conn[j]]=1;
1487           else
1488             {
1489               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1490               throw INTERP_KERNEL::Exception(oss.str().c_str());
1491             }
1492         }
1493   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1494   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1495   return ret.retn();
1496 }
1497
1498 /*!
1499  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1500  * For each cell in \b this the number of nodes constituting cell is computed.
1501  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1502  * So for pohyhedrons some nodes can be counted several times in the returned result.
1503  * 
1504  * \return a newly allocated array
1505  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1506  */
1507 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1508 {
1509   checkConnectivityFullyDefined();
1510   int nbOfCells=getNumberOfCells();
1511   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1512   ret->alloc(nbOfCells,1);
1513   int *retPtr=ret->getPointer();
1514   const int *conn=getNodalConnectivity()->getConstPointer();
1515   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1516   for(int i=0;i<nbOfCells;i++,retPtr++)
1517     {
1518       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1519         *retPtr=connI[i+1]-connI[i]-1;
1520       else
1521         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1522     }
1523   return ret.retn();
1524 }
1525
1526 /*!
1527  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1528  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1529  *
1530  * \return DataArrayInt * - new object to be deallocated by the caller.
1531  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1532  */
1533 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1534 {
1535   checkConnectivityFullyDefined();
1536   int nbOfCells=getNumberOfCells();
1537   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1538   ret->alloc(nbOfCells,1);
1539   int *retPtr=ret->getPointer();
1540   const int *conn=getNodalConnectivity()->getConstPointer();
1541   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1542   for(int i=0;i<nbOfCells;i++,retPtr++)
1543     {
1544       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1545       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1546         *retPtr=(int)s.size();
1547       else
1548         {
1549           s.erase(-1);
1550           *retPtr=(int)s.size();
1551         }
1552     }
1553   return ret.retn();
1554 }
1555
1556 /*!
1557  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1558  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1559  * 
1560  * \return a newly allocated array
1561  */
1562 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1563 {
1564   checkConnectivityFullyDefined();
1565   int nbOfCells=getNumberOfCells();
1566   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1567   ret->alloc(nbOfCells,1);
1568   int *retPtr=ret->getPointer();
1569   const int *conn=getNodalConnectivity()->getConstPointer();
1570   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1571   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1572     {
1573       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1574       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1575     }
1576   return ret.retn();
1577 }
1578
1579 /*!
1580  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1581  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1582  * array mean that the corresponding old node is no more used. 
1583  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1584  *           this->getNumberOfNodes() before call of this method. The caller is to
1585  *           delete this array using decrRef() as it is no more needed. 
1586  *  \throw If the coordinates array is not set.
1587  *  \throw If the nodal connectivity of cells is not defined.
1588  *  \throw If the nodal connectivity includes an invalid id.
1589  *  \sa areAllNodesFetched
1590  *
1591  *  \if ENABLE_EXAMPLES
1592  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1593  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1594  *  \endif
1595  */
1596 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1597 {
1598   return MEDCouplingPointSet::zipCoordsTraducer();
1599 }
1600
1601 /*!
1602  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1603  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1604  */
1605 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1606 {
1607   switch(compType)
1608   {
1609     case 0:
1610       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1611     case 1:
1612       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1613     case 2:
1614       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1615     case 3:
1616       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1617     case 7:
1618       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1619   }
1620   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1621 }
1622
1623 /*!
1624  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1625  */
1626 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1627 {
1628   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1629     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1630   return 0;
1631 }
1632
1633 /*!
1634  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1635  */
1636 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1637 {
1638   int sz=connI[cell1+1]-connI[cell1];
1639   if(sz==connI[cell2+1]-connI[cell2])
1640     {
1641       if(conn[connI[cell1]]==conn[connI[cell2]])
1642         {
1643           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1644           unsigned dim=cm.getDimension();
1645           if(dim!=3)
1646             {
1647               if(dim!=1)
1648                 {
1649                   int sz1=2*(sz-1);
1650                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1651                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1652                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1653                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1654                   return work!=tmp+sz1?1:0;
1655                 }
1656               else
1657                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1658             }
1659           else
1660             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1661         }
1662     }
1663   return 0;
1664 }
1665
1666 /*!
1667  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1668  */
1669 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1670 {
1671   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1672     {
1673       if(conn[connI[cell1]]==conn[connI[cell2]])
1674         {
1675           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1676           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1677           return s1==s2?1:0;
1678         }
1679     }
1680   return 0;
1681 }
1682
1683 /*!
1684  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1685  */
1686 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1687 {
1688   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1689     {
1690       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1691       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1692       return s1==s2?1:0;
1693     }
1694   return 0;
1695 }
1696
1697 /*!
1698  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1699  */
1700 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1701 {
1702   int sz=connI[cell1+1]-connI[cell1];
1703   if(sz==connI[cell2+1]-connI[cell2])
1704     {
1705       if(conn[connI[cell1]]==conn[connI[cell2]])
1706         {
1707           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1708           unsigned dim=cm.getDimension();
1709           if(dim!=3)
1710             {
1711               if(dim!=1)
1712                 {
1713                   int sz1=2*(sz-1);
1714                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1715                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1716                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1717                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1718                   if(work!=tmp+sz1)
1719                     return 1;
1720                   else
1721                     {
1722                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1723                       std::reverse_iterator<int *> it2((int *)tmp);
1724                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1725                         return 2;
1726                       else
1727                         return 0;
1728                     }
1729
1730                   return work!=tmp+sz1?1:0;
1731                 }
1732               else
1733                 {//case of SEG2 and SEG3
1734                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1735                     return 1;
1736                   if(!cm.isQuadratic())
1737                     {
1738                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1739                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1740                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1741                         return 2;
1742                       return 0;
1743                     }
1744                   else
1745                     {
1746                       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])
1747                         return 2;
1748                       return 0;
1749                     }
1750                 }
1751             }
1752           else
1753             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1754         }
1755     }
1756   return 0;
1757 }
1758
1759 /*!
1760  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1761  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1762  * and result remains unchanged.
1763  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1764  * If in 'candidates' pool -1 value is considered as an empty value.
1765  * WARNING this method returns only ONE set of result !
1766  */
1767 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1768 {
1769   if(candidates.size()<1)
1770     return false;
1771   bool ret=false;
1772   std::vector<int>::const_iterator iter=candidates.begin();
1773   int start=(*iter++);
1774   for(;iter!=candidates.end();iter++)
1775     {
1776       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1777       if(status!=0)
1778         {
1779           if(!ret)
1780             {
1781               result->pushBackSilent(start);
1782               ret=true;
1783             }
1784           if(status==1)
1785             result->pushBackSilent(*iter);
1786           else
1787             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1788         }
1789     }
1790   return ret;
1791 }
1792
1793 /*!
1794  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1795  * by \a compType.
1796  * This method keeps the coordiantes of \a this. This method is time consuming.
1797  *
1798  * \param [in] compType input specifying the technique used to compare cells each other.
1799  *   - 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.
1800  *   - 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)
1801  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1802  *   - 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
1803  * can be used for users not sensitive to orientation of cell
1804  * \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.
1805  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1806  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1807  * \return the correspondance array old to new in a newly allocated array.
1808  * 
1809  */
1810 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1811 {
1812   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1813   getReverseNodalConnectivity(revNodal,revNodalI);
1814   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1815 }
1816
1817 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1818                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1819 {
1820   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1821   int nbOfCells=nodalI->getNumberOfTuples()-1;
1822   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1823   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1824   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1825   std::vector<bool> isFetched(nbOfCells,false);
1826   if(startCellId==0)
1827     {
1828       for(int i=0;i<nbOfCells;i++)
1829         {
1830           if(!isFetched[i])
1831             {
1832               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1833               std::vector<int> v,v2;
1834               if(connOfNode!=connPtr+connIPtr[i+1])
1835                 {
1836                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1837                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1838                   connOfNode++;
1839                 }
1840               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1841                 if(*connOfNode>=0)
1842                   {
1843                     v=v2;
1844                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1845                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1846                     v2.resize(std::distance(v2.begin(),it));
1847                   }
1848               if(v2.size()>1)
1849                 {
1850                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1851                     {
1852                       int pos=commonCellsI->back();
1853                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1854                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1855                         isFetched[*it]=true;
1856                     }
1857                 }
1858             }
1859         }
1860     }
1861   else
1862     {
1863       for(int i=startCellId;i<nbOfCells;i++)
1864         {
1865           if(!isFetched[i])
1866             {
1867               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1868               std::vector<int> v,v2;
1869               if(connOfNode!=connPtr+connIPtr[i+1])
1870                 {
1871                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1872                   connOfNode++;
1873                 }
1874               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1875                 if(*connOfNode>=0)
1876                   {
1877                     v=v2;
1878                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1879                     v2.resize(std::distance(v2.begin(),it));
1880                   }
1881               if(v2.size()>1)
1882                 {
1883                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1884                     {
1885                       int pos=commonCellsI->back();
1886                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1887                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1888                         isFetched[*it]=true;
1889                     }
1890                 }
1891             }
1892         }
1893     }
1894   commonCellsArr=commonCells.retn();
1895   commonCellsIArr=commonCellsI.retn();
1896 }
1897
1898 /*!
1899  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1900  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1901  * than \a other->getNumberOfCells() in the returned array means that there is no
1902  * corresponding cell in \a this mesh.
1903  * It is expected that \a this and \a other meshes share the same node coordinates
1904  * array, if it is not so an exception is thrown. 
1905  *  \param [in] other - the mesh to compare with.
1906  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1907  *         valid values [0,1,2], see zipConnectivityTraducer().
1908  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1909  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1910  *         values. The caller is to delete this array using
1911  *         decrRef() as it is no more needed.
1912  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1913  *         mesh.
1914  *
1915  *  \if ENABLE_EXAMPLES
1916  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1917  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1918  *  \endif
1919  *  \sa checkDeepEquivalOnSameNodesWith()
1920  *  \sa checkGeoEquivalWith()
1921  */
1922 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1923 {
1924   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1925   int nbOfCells=getNumberOfCells();
1926   static const int possibleCompType[]={0,1,2};
1927   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1928     {
1929       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1930       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1931       oss << " !";
1932       throw INTERP_KERNEL::Exception(oss.str().c_str());
1933     }
1934   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1935   arr=o2n->subArray(nbOfCells);
1936   arr->setName(other->getName());
1937   int tmp;
1938   if(other->getNumberOfCells()==0)
1939     return true;
1940   return arr->getMaxValue(tmp)<nbOfCells;
1941 }
1942
1943 /*!
1944  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1945  * This method tries to determine if \b other is fully included in \b this.
1946  * The main difference is that this method is not expected to throw exception.
1947  * This method has two outputs :
1948  *
1949  * \param other other mesh
1950  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1951  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1952  */
1953 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1954 {
1955   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1956   DataArrayInt *commonCells=0,*commonCellsI=0;
1957   int thisNbCells=getNumberOfCells();
1958   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1959   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1960   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1961   int otherNbCells=other->getNumberOfCells();
1962   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1963   arr2->alloc(otherNbCells,1);
1964   arr2->fillWithZero();
1965   int *arr2Ptr=arr2->getPointer();
1966   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1967   for(int i=0;i<nbOfCommon;i++)
1968     {
1969       int start=commonCellsPtr[commonCellsIPtr[i]];
1970       if(start<thisNbCells)
1971         {
1972           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1973             {
1974               int sig=commonCellsPtr[j]>0?1:-1;
1975               int val=std::abs(commonCellsPtr[j])-1;
1976               if(val>=thisNbCells)
1977                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1978             }
1979         }
1980     }
1981   arr2->setName(other->getName());
1982   if(arr2->presenceOfValue(0))
1983     return false;
1984   arr=arr2.retn();
1985   return true;
1986 }
1987
1988 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1989 {
1990   if(!other)
1991     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1992   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1993   if(!otherC)
1994     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1995   std::vector<const MEDCouplingUMesh *> ms(2);
1996   ms[0]=this;
1997   ms[1]=otherC;
1998   return MergeUMeshesOnSameCoords(ms);
1999 }
2000
2001 /*!
2002  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2003  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2004  * cellIds is not given explicitely but by a range python like.
2005  * 
2006  * \param start
2007  * \param end
2008  * \param step
2009  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see MEDCoupling::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2010  * \return a newly allocated
2011  * 
2012  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2013  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2014  */
2015 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
2016 {
2017   if(getMeshDimension()!=-1)
2018     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
2019   else
2020     {
2021       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
2022       if(newNbOfCells!=1)
2023         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2024       if(start!=0)
2025         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2026       incrRef();
2027       return const_cast<MEDCouplingUMesh *>(this);
2028     }
2029 }
2030
2031 /*!
2032  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2033  * The result mesh shares or not the node coordinates array with \a this mesh depending
2034  * on \a keepCoords parameter.
2035  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2036  *           to write this mesh to the MED file, its cells must be sorted using
2037  *           sortCellsInMEDFileFrmt().
2038  *  \param [in] begin - an array of cell ids to include to the new mesh.
2039  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2040  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2041  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2042  *         by calling zipCoords().
2043  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2044  *         to delete this mesh using decrRef() as it is no more needed. 
2045  *  \throw If the coordinates array is not set.
2046  *  \throw If the nodal connectivity of cells is not defined.
2047  *  \throw If any cell id in the array \a begin is not valid.
2048  *
2049  *  \if ENABLE_EXAMPLES
2050  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2051  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2052  *  \endif
2053  */
2054 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2055 {
2056   if(getMeshDimension()!=-1)
2057     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2058   else
2059     {
2060       if(end-begin!=1)
2061         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2062       if(begin[0]!=0)
2063         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2064       incrRef();
2065       return const_cast<MEDCouplingUMesh *>(this);
2066     }
2067 }
2068
2069 /*!
2070  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2071  *
2072  * 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.
2073  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2074  * The number of cells of \b this will remain the same with this method.
2075  *
2076  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2077  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2078  * \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 ).
2079  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2080  */
2081 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2082 {
2083   checkConnectivityFullyDefined();
2084   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2085   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2086     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2087   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2088     {
2089       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2090       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2091       throw INTERP_KERNEL::Exception(oss.str().c_str());
2092     }
2093   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2094   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2095     {
2096       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2097       throw INTERP_KERNEL::Exception(oss.str().c_str());
2098     }
2099   int nbOfCells=getNumberOfCells();
2100   bool easyAssign=true;
2101   const int *connI=_nodal_connec_index->getConstPointer();
2102   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2103   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2104     {
2105       if(*it>=0 && *it<nbOfCells)
2106         {
2107           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2108         }
2109       else
2110         {
2111           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2112           throw INTERP_KERNEL::Exception(oss.str().c_str());
2113         }
2114     }
2115   if(easyAssign)
2116     {
2117       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2118       computeTypes();
2119     }
2120   else
2121     {
2122       DataArrayInt *arrOut=0,*arrIOut=0;
2123       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2124                                                arrOut,arrIOut);
2125       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2126       setConnectivity(arrOut,arrIOut,true);
2127     }
2128 }
2129
2130 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2131 {
2132   checkConnectivityFullyDefined();
2133   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2134   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2135     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2136   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2137     {
2138       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2139       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2140       throw INTERP_KERNEL::Exception(oss.str().c_str());
2141     }
2142   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2143   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2144     {
2145       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2146       throw INTERP_KERNEL::Exception(oss.str().c_str());
2147     }
2148   int nbOfCells=getNumberOfCells();
2149   bool easyAssign=true;
2150   const int *connI=_nodal_connec_index->getConstPointer();
2151   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2152   int it=start;
2153   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2154     {
2155       if(it>=0 && it<nbOfCells)
2156         {
2157           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2158         }
2159       else
2160         {
2161           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2162           throw INTERP_KERNEL::Exception(oss.str().c_str());
2163         }
2164     }
2165   if(easyAssign)
2166     {
2167       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2168       computeTypes();
2169     }
2170   else
2171     {
2172       DataArrayInt *arrOut=0,*arrIOut=0;
2173       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2174                                                 arrOut,arrIOut);
2175       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2176       setConnectivity(arrOut,arrIOut,true);
2177     }
2178 }                      
2179
2180 /*!
2181  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2182  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2183  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2184  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2185  *
2186  * \param [in] begin input start of array of node ids.
2187  * \param [in] end input end of array of node ids.
2188  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2189  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2190  */
2191 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2192 {
2193   MCAuto<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2194   checkConnectivityFullyDefined();
2195   int tmp=-1;
2196   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2197   std::vector<bool> fastFinder(sz,false);
2198   for(const int *work=begin;work!=end;work++)
2199     if(*work>=0 && *work<sz)
2200       fastFinder[*work]=true;
2201   int nbOfCells=getNumberOfCells();
2202   const int *conn=getNodalConnectivity()->getConstPointer();
2203   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2204   for(int i=0;i<nbOfCells;i++)
2205     {
2206       int ref=0,nbOfHit=0;
2207       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2208         if(*work2>=0)
2209           {
2210             ref++;
2211             if(fastFinder[*work2])
2212               nbOfHit++;
2213           }
2214       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2215         cellIdsKept->pushBackSilent(i);
2216     }
2217   cellIdsKeptArr=cellIdsKept.retn();
2218 }
2219
2220 /*!
2221  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2222  * this->getMeshDimension(), that bound some cells of \a this mesh.
2223  * The cells of lower dimension to include to the result mesh are selected basing on
2224  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2225  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2226  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2227  * created mesh shares the node coordinates array with \a this mesh. 
2228  *  \param [in] begin - the array of node ids.
2229  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2230  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2231  *         array \a begin are added, else cells whose any node is in the
2232  *         array \a begin are added.
2233  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2234  *         to delete this mesh using decrRef() as it is no more needed. 
2235  *  \throw If the coordinates array is not set.
2236  *  \throw If the nodal connectivity of cells is not defined.
2237  *  \throw If any node id in \a begin is not valid.
2238  *
2239  *  \if ENABLE_EXAMPLES
2240  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2241  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2242  *  \endif
2243  */
2244 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2245 {
2246   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2247   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2248   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2249   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2250   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2251 }
2252
2253 /*!
2254  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2255  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2256  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2257  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2258  *         by calling zipCoords().
2259  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2260  *         to delete this mesh using decrRef() as it is no more needed. 
2261  *  \throw If the coordinates array is not set.
2262  *  \throw If the nodal connectivity of cells is not defined.
2263  *
2264  *  \if ENABLE_EXAMPLES
2265  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2266  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2267  *  \endif
2268  */
2269 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2270 {
2271   DataArrayInt *desc=DataArrayInt::New();
2272   DataArrayInt *descIndx=DataArrayInt::New();
2273   DataArrayInt *revDesc=DataArrayInt::New();
2274   DataArrayInt *revDescIndx=DataArrayInt::New();
2275   //
2276   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2277   revDesc->decrRef();
2278   desc->decrRef();
2279   descIndx->decrRef();
2280   int nbOfCells=meshDM1->getNumberOfCells();
2281   const int *revDescIndxC=revDescIndx->getConstPointer();
2282   std::vector<int> boundaryCells;
2283   for(int i=0;i<nbOfCells;i++)
2284     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2285       boundaryCells.push_back(i);
2286   revDescIndx->decrRef();
2287   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2288   return ret;
2289 }
2290
2291 /*!
2292  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2293  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2294  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2295  */
2296 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2297 {
2298   checkFullyDefined();
2299   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2300   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2301   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2302   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2303   //
2304   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2305   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2306   //
2307   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2308   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2309   const int *revDescPtr=revDesc->getConstPointer();
2310   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2311   int nbOfCells=getNumberOfCells();
2312   std::vector<bool> ret1(nbOfCells,false);
2313   int sz=0;
2314   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2315     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2316       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2317   //
2318   DataArrayInt *ret2=DataArrayInt::New();
2319   ret2->alloc(sz,1);
2320   int *ret2Ptr=ret2->getPointer();
2321   sz=0;
2322   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2323     if(*it)
2324       *ret2Ptr++=sz;
2325   ret2->setName("BoundaryCells");
2326   return ret2;
2327 }
2328
2329 /*!
2330  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2331  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2332  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2333  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2334  *
2335  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2336  * This method also returns the cells ids set s1 which contains the cell ids in \b this for which one of the dim-1 constituent
2337  * equals a cell in \b otherDimM1OnSameCoords.
2338  *
2339  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2340  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2341  *
2342  * \param [in] otherDimM1OnSameCoords
2343  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2344  * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1 \b indexed into the \b cellIdsRk0 subset. To get the absolute ids of s1, simply invoke
2345  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2346  */
2347 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2348 {
2349   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2350     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2351   checkConnectivityFullyDefined();
2352   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2353   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2355   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2356   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2357   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2358   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2359   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2360   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2361   DataArrayInt *idsOtherInConsti=0;
2362   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2363   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2364   if(!b)
2365     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2366   std::set<int> s1;
2367   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2368     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2369   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2370   s1arr_renum1->sort();
2371   cellIdsRk0=s0arr.retn();
2372   //cellIdsRk1=s_renum1.retn();
2373   cellIdsRk1=s1arr_renum1.retn();
2374 }
2375
2376 /*!
2377  * 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
2378  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2379  * 
2380  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2381  */
2382 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2383 {
2384   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2385   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2386   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2387   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2388   //
2389   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2390   revDesc=0; desc=0; descIndx=0;
2391   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2392   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2393   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2394 }
2395
2396 /*!
2397  * Finds nodes lying on the boundary of \a this mesh.
2398  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2399  *          nodes. The caller is to delete this array using decrRef() as it is no
2400  *          more needed.
2401  *  \throw If the coordinates array is not set.
2402  *  \throw If the nodal connectivity of cells is node defined.
2403  *
2404  *  \if ENABLE_EXAMPLES
2405  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2406  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2407  *  \endif
2408  */
2409 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2410 {
2411   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2412   return skin->computeFetchedNodeIds();
2413 }
2414
2415 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2416 {
2417   incrRef();
2418   return const_cast<MEDCouplingUMesh *>(this);
2419 }
2420
2421 /*!
2422  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2423  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2424  * 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.
2425  * 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.
2426  * 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.
2427  *
2428  * \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
2429  *             parameter is altered during the call.
2430  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2431  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2432  * \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.
2433  *
2434  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2435  */
2436 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2437                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2438 {
2439   typedef MCAuto<DataArrayInt> DAInt;
2440
2441   checkFullyDefined();
2442   otherDimM1OnSameCoords.checkFullyDefined();
2443   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2444     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2445   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2447   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2448   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2449   DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2450   DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2451   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2452   MCAuto<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2453   DAInt s1=m0Part->computeFetchedNodeIds();
2454   DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2455   DAInt s3=s2->buildSubstraction(s1);
2456   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2457   //
2458   MCAuto<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2459   int nCells2 = m0Part2->getNumberOfCells();
2460   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2461   MCAuto<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2462   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2463   DataArrayInt *tmp00=0,*tmp11=0;
2464   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2465   DAInt neighInit00(tmp00);
2466   DAInt neighIInit00(tmp11);
2467   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2468   DataArrayInt *idsTmp=0;
2469   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2470   DAInt ids(idsTmp);
2471   if(!b)
2472     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2473   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2474   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2475   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2476   DataArrayInt *tmp0=0,*tmp1=0;
2477   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2478   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2479   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2480   DAInt neigh00(tmp0);
2481   DAInt neighI00(tmp1);
2482
2483   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2484   int seed = 0, nIter = 0;
2485   int nIterMax = nCells2+1; // Safety net for the loop
2486   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2487   hitCells->fillWithValue(-1);
2488   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2489   cellsToModifyConn0_torenum->alloc(0,1);
2490   while (nIter < nIterMax)
2491     {
2492       DAInt t = hitCells->findIdsEqual(-1);
2493       if (!t->getNumberOfTuples())
2494         break;
2495       // Connex zone without the crack (to compute the next seed really)
2496       int dnu;
2497       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2498       int cnt = 0;
2499       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2500         hitCells->setIJ(*ptr,0,1);
2501       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2502       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2503       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2504       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2505       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2506       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2507       DAInt intersec = nonHitCells->buildIntersection(comple);
2508       if (intersec->getNumberOfTuples())
2509         { seed = intersec->getIJ(0,0); }
2510       else
2511         { break; }
2512       nIter++;
2513     }
2514   if (nIter >= nIterMax)
2515     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2516
2517   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2518   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2519   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2520   //
2521   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2522   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2523   nodeIdsToDuplicate=s3.retn();
2524 }
2525
2526 /*!
2527  * This method operates a modification of the connectivity and coords in \b this.
2528  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2529  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2530  * 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
2531  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2532  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2533  * 
2534  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2535  * 
2536  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2537  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2538  */
2539 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2540 {
2541   int nbOfNodes=getNumberOfNodes();
2542   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2543   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2544 }
2545
2546 /*!
2547  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2548  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2549  *
2550  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2551  *
2552  * \sa renumberNodesInConn
2553  */
2554 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2555 {
2556   checkConnectivityFullyDefined();
2557   int *conn(getNodalConnectivity()->getPointer());
2558   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2559   int nbOfCells(getNumberOfCells());
2560   for(int i=0;i<nbOfCells;i++)
2561     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2562       {
2563         int& node=conn[iconn];
2564         if(node>=0)//avoid polyhedron separator
2565           {
2566             node+=offset;
2567           }
2568       }
2569   _nodal_connec->declareAsNew();
2570   updateTime();
2571 }
2572
2573 /*!
2574  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2575  *  of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2576  *  of a big mesh.
2577  */
2578 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2579 {
2580   checkConnectivityFullyDefined();
2581   int *conn(getNodalConnectivity()->getPointer());
2582   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2583   int nbOfCells(getNumberOfCells());
2584   for(int i=0;i<nbOfCells;i++)
2585     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2586       {
2587         int& node=conn[iconn];
2588         if(node>=0)//avoid polyhedron separator
2589           {
2590             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2591             if(it!=newNodeNumbersO2N.end())
2592               {
2593                 node=(*it).second;
2594               }
2595             else
2596               {
2597                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2598                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2599               }
2600           }
2601       }
2602   _nodal_connec->declareAsNew();
2603   updateTime();
2604 }
2605
2606 /*!
2607  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2608  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2609  * This method is a generalization of shiftNodeNumbersInConn().
2610  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2611  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2612  *         this->getNumberOfNodes(), in "Old to New" mode. 
2613  *         See \ref numbering for more info on renumbering modes.
2614  *  \throw If the nodal connectivity of cells is not defined.
2615  *
2616  *  \if ENABLE_EXAMPLES
2617  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2618  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2619  *  \endif
2620  */
2621 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2622 {
2623   checkConnectivityFullyDefined();
2624   int *conn=getNodalConnectivity()->getPointer();
2625   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2626   int nbOfCells(getNumberOfCells());
2627   for(int i=0;i<nbOfCells;i++)
2628     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2629       {
2630         int& node=conn[iconn];
2631         if(node>=0)//avoid polyhedron separator
2632           {
2633             node=newNodeNumbersO2N[node];
2634           }
2635       }
2636   _nodal_connec->declareAsNew();
2637   updateTime();
2638 }
2639
2640 /*!
2641  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2642  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2643  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2644  * 
2645  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2646  */
2647 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2648 {
2649   checkConnectivityFullyDefined();
2650   int *conn=getNodalConnectivity()->getPointer();
2651   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2652   int nbOfCells=getNumberOfCells();
2653   for(int i=0;i<nbOfCells;i++)
2654     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2655       {
2656         int& node=conn[iconn];
2657         if(node>=0)//avoid polyhedron separator
2658           {
2659             node+=delta;
2660           }
2661       }
2662   _nodal_connec->declareAsNew();
2663   updateTime();
2664 }
2665
2666 /*!
2667  * This method operates a modification of the connectivity in \b this.
2668  * 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.
2669  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2670  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2671  * 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
2672  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2673  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2674  * 
2675  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2676  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2677  * 
2678  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2679  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2680  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2681  */
2682 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2683 {
2684   checkConnectivityFullyDefined();
2685   std::map<int,int> m;
2686   int val=offset;
2687   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2688     m[*work]=val;
2689   int *conn=getNodalConnectivity()->getPointer();
2690   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2691   int nbOfCells=getNumberOfCells();
2692   for(int i=0;i<nbOfCells;i++)
2693     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2694       {
2695         int& node=conn[iconn];
2696         if(node>=0)//avoid polyhedron separator
2697           {
2698             std::map<int,int>::iterator it=m.find(node);
2699             if(it!=m.end())
2700               node=(*it).second;
2701           }
2702       }
2703   updateTime();
2704 }
2705
2706 /*!
2707  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2708  *
2709  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2710  * After the call of this method the number of cells remains the same as before.
2711  *
2712  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2713  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2714  * be strictly in [0;this->getNumberOfCells()).
2715  *
2716  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2717  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2718  * should be contained in[0;this->getNumberOfCells()).
2719  * 
2720  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2721  * \param check
2722  */
2723 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2724 {
2725   checkConnectivityFullyDefined();
2726   int nbCells=getNumberOfCells();
2727   const int *array=old2NewBg;
2728   if(check)
2729     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2730   //
2731   const int *conn=_nodal_connec->getConstPointer();
2732   const int *connI=_nodal_connec_index->getConstPointer();
2733   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2734   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2735   const int *n2oPtr=n2o->begin();
2736   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2737   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2738   newConn->copyStringInfoFrom(*_nodal_connec);
2739   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2740   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2741   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2742   //
2743   int *newC=newConn->getPointer();
2744   int *newCI=newConnI->getPointer();
2745   int loc=0;
2746   newCI[0]=loc;
2747   for(int i=0;i<nbCells;i++)
2748     {
2749       int pos=n2oPtr[i];
2750       int nbOfElts=connI[pos+1]-connI[pos];
2751       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2752       loc+=nbOfElts;
2753       newCI[i+1]=loc;
2754     }
2755   //
2756   setConnectivity(newConn,newConnI);
2757   if(check)
2758     free(const_cast<int *>(array));
2759 }
2760
2761 /*!
2762  * Finds cells whose bounding boxes intersect a given bounding box.
2763  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2764  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2765  *         zMax (if in 3D). 
2766  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2767  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2768  *         extent of the bounding box of cell to produce an addition to this bounding box.
2769  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2770  *         cells. The caller is to delete this array using decrRef() as it is no more
2771  *         needed. 
2772  *  \throw If the coordinates array is not set.
2773  *  \throw If the nodal connectivity of cells is not defined.
2774  *
2775  *  \if ENABLE_EXAMPLES
2776  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2777  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2778  *  \endif
2779  */
2780 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2781 {
2782   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2783   if(getMeshDimension()==-1)
2784     {
2785       elems->pushBackSilent(0);
2786       return elems.retn();
2787     }
2788   int dim=getSpaceDimension();
2789   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2790   const int* conn      = getNodalConnectivity()->getConstPointer();
2791   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2792   const double* coords = getCoords()->getConstPointer();
2793   int nbOfCells=getNumberOfCells();
2794   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2795     {
2796       for (int i=0; i<dim; i++)
2797         {
2798           elem_bb[i*2]=std::numeric_limits<double>::max();
2799           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2800         }
2801
2802       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2803         {
2804           int node= conn[inode];
2805           if(node>=0)//avoid polyhedron separator
2806             {
2807               for (int idim=0; idim<dim; idim++)
2808                 {
2809                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2810                     {
2811                       elem_bb[idim*2] = coords[node*dim+idim] ;
2812                     }
2813                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2814                     {
2815                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2816                     }
2817                 }
2818             }
2819         }
2820       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2821         elems->pushBackSilent(ielem);
2822     }
2823   return elems.retn();
2824 }
2825
2826 /*!
2827  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2828  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2829  * added in 'elems' parameter.
2830  */
2831 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2832 {
2833   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2834   if(getMeshDimension()==-1)
2835     {
2836       elems->pushBackSilent(0);
2837       return elems.retn();
2838     }
2839   int dim=getSpaceDimension();
2840   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2841   const int* conn      = getNodalConnectivity()->getConstPointer();
2842   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2843   const double* coords = getCoords()->getConstPointer();
2844   int nbOfCells=getNumberOfCells();
2845   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2846     {
2847       for (int i=0; i<dim; i++)
2848         {
2849           elem_bb[i*2]=std::numeric_limits<double>::max();
2850           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2851         }
2852
2853       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2854         {
2855           int node= conn[inode];
2856           if(node>=0)//avoid polyhedron separator
2857             {
2858               for (int idim=0; idim<dim; idim++)
2859                 {
2860                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2861                     {
2862                       elem_bb[idim*2] = coords[node*dim+idim] ;
2863                     }
2864                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2865                     {
2866                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2867                     }
2868                 }
2869             }
2870         }
2871       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2872         elems->pushBackSilent(ielem);
2873     }
2874   return elems.retn();
2875 }
2876
2877 /*!
2878  * Returns a type of a cell by its id.
2879  *  \param [in] cellId - the id of the cell of interest.
2880  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2881  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2882  */
2883 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2884 {
2885   const int *ptI=_nodal_connec_index->getConstPointer();
2886   const int *pt=_nodal_connec->getConstPointer();
2887   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2888     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2889   else
2890     {
2891       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2892       throw INTERP_KERNEL::Exception(oss.str().c_str());
2893     }
2894 }
2895
2896 /*!
2897  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2898  * This method does not throw exception if geometric type \a type is not in \a this.
2899  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2900  * The coordinates array is not considered here.
2901  *
2902  * \param [in] type the geometric type
2903  * \return cell ids in this having geometric type \a type.
2904  */
2905 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2906 {
2907
2908   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2909   ret->alloc(0,1);
2910   checkConnectivityFullyDefined();
2911   int nbCells=getNumberOfCells();
2912   int mdim=getMeshDimension();
2913   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2914   if(mdim!=(int)cm.getDimension())
2915     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2916   const int *ptI=_nodal_connec_index->getConstPointer();
2917   const int *pt=_nodal_connec->getConstPointer();
2918   for(int i=0;i<nbCells;i++)
2919     {
2920       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2921         ret->pushBackSilent(i);
2922     }
2923   return ret.retn();
2924 }
2925
2926 /*!
2927  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2928  */
2929 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2930 {
2931   const int *ptI=_nodal_connec_index->getConstPointer();
2932   const int *pt=_nodal_connec->getConstPointer();
2933   int nbOfCells=getNumberOfCells();
2934   int ret=0;
2935   for(int i=0;i<nbOfCells;i++)
2936     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2937       ret++;
2938   return ret;
2939 }
2940
2941 /*!
2942  * Returns the nodal connectivity of a given cell.
2943  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2944  * all returned node ids can be used in getCoordinatesOfNode().
2945  *  \param [in] cellId - an id of the cell of interest.
2946  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2947  *         cleared before the appending.
2948  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2949  */
2950 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2951 {
2952   const int *ptI=_nodal_connec_index->getConstPointer();
2953   const int *pt=_nodal_connec->getConstPointer();
2954   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2955     if(*w>=0)
2956       conn.push_back(*w);
2957 }
2958
2959 std::string MEDCouplingUMesh::simpleRepr() const
2960 {
2961   static const char msg0[]="No coordinates specified !";
2962   std::ostringstream ret;
2963   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2964   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2965   int tmpp1,tmpp2;
2966   double tt=getTime(tmpp1,tmpp2);
2967   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2968   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2969   if(_mesh_dim>=-1)
2970     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2971   else
2972     { ret << " Mesh dimension has not been set or is invalid !"; }
2973   if(_coords!=0)
2974     {
2975       const int spaceDim=getSpaceDimension();
2976       ret << spaceDim << "\nInfo attached on space dimension : ";
2977       for(int i=0;i<spaceDim;i++)
2978         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2979       ret << "\n";
2980     }
2981   else
2982     ret << msg0 << "\n";
2983   ret << "Number of nodes : ";
2984   if(_coords!=0)
2985     ret << getNumberOfNodes() << "\n";
2986   else
2987     ret << msg0 << "\n";
2988   ret << "Number of cells : ";
2989   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2990     ret << getNumberOfCells() << "\n";
2991   else
2992     ret << "No connectivity specified !" << "\n";
2993   ret << "Cell types present : ";
2994   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2995     {
2996       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2997       ret << cm.getRepr() << " ";
2998     }
2999   ret << "\n";
3000   return ret.str();
3001 }
3002
3003 std::string MEDCouplingUMesh::advancedRepr() const
3004 {
3005   std::ostringstream ret;
3006   ret << simpleRepr();
3007   ret << "\nCoordinates array : \n___________________\n\n";
3008   if(_coords)
3009     _coords->reprWithoutNameStream(ret);
3010   else
3011     ret << "No array set !\n";
3012   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3013   reprConnectivityOfThisLL(ret);
3014   return ret.str();
3015 }
3016
3017 /*!
3018  * This method returns a C++ code that is a dump of \a this.
3019  * This method will throw if this is not fully defined.
3020  */
3021 std::string MEDCouplingUMesh::cppRepr() const
3022 {
3023   static const char coordsName[]="coords";
3024   static const char connName[]="conn";
3025   static const char connIName[]="connI";
3026   checkFullyDefined();
3027   std::ostringstream ret; ret << "// coordinates" << std::endl;
3028   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3029   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3030   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3031   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3032   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3033   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3034   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3035   return ret.str();
3036 }
3037
3038 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3039 {
3040   std::ostringstream ret;
3041   reprConnectivityOfThisLL(ret);
3042   return ret.str();
3043 }
3044
3045 /*!
3046  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3047  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3048  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3049  * some algos).
3050  * 
3051  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3052  * 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
3053  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3054  */
3055 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3056 {
3057   int mdim=getMeshDimension();
3058   if(mdim<0)
3059     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3060   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3061   MCAuto<DataArrayInt> tmp1,tmp2;
3062   bool needToCpyCT=true;
3063   if(!_nodal_connec)
3064     {
3065       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3066       needToCpyCT=false;
3067     }
3068   else
3069     {
3070       tmp1=_nodal_connec;
3071       tmp1->incrRef();
3072     }
3073   if(!_nodal_connec_index)
3074     {
3075       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3076       needToCpyCT=false;
3077     }
3078   else
3079     {
3080       tmp2=_nodal_connec_index;
3081       tmp2->incrRef();
3082     }
3083   ret->setConnectivity(tmp1,tmp2,false);
3084   if(needToCpyCT)
3085     ret->_types=_types;
3086   if(!_coords)
3087     {
3088       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3089       ret->setCoords(coords);
3090     }
3091   else
3092     ret->setCoords(_coords);
3093   return ret.retn();
3094 }
3095
3096 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3097 {
3098   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3099     {
3100       int nbOfCells=getNumberOfCells();
3101       const int *c=_nodal_connec->getConstPointer();
3102       const int *ci=_nodal_connec_index->getConstPointer();
3103       for(int i=0;i<nbOfCells;i++)
3104         {
3105           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3106           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3107           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3108           stream << "\n";
3109         }
3110     }
3111   else
3112     stream << "Connectivity not defined !\n";
3113 }
3114
3115 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3116 {
3117   const int *ptI=_nodal_connec_index->getConstPointer();
3118   const int *pt=_nodal_connec->getConstPointer();
3119   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3120     return ptI[cellId+1]-ptI[cellId]-1;
3121   else
3122     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3123 }
3124
3125 /*!
3126  * Returns types of cells of the specified part of \a this mesh.
3127  * This method avoids computing sub-mesh explicitely to get its types.
3128  *  \param [in] begin - an array of cell ids of interest.
3129  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3130  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3131  *         describing the cell types. 
3132  *  \throw If the coordinates array is not set.
3133  *  \throw If the nodal connectivity of cells is not defined.
3134  *  \sa getAllGeoTypes()
3135  */
3136 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3137 {
3138   checkFullyDefined();
3139   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3140   const int *conn=_nodal_connec->getConstPointer();
3141   const int *connIndex=_nodal_connec_index->getConstPointer();
3142   for(const int *w=begin;w!=end;w++)
3143     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3144   return ret;
3145 }
3146
3147 /*!
3148  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3149  * Optionally updates
3150  * a set of types of cells constituting \a this mesh. 
3151  * This method is for advanced users having prepared their connectivity before. For
3152  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3153  *  \param [in] conn - the nodal connectivity array. 
3154  *  \param [in] connIndex - the nodal connectivity index array.
3155  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3156  *         mesh is updated.
3157  */
3158 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3159 {
3160   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3161   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3162   if(isComputingTypes)
3163     computeTypes();
3164   declareAsNew();
3165 }
3166
3167 /*!
3168  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3169  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3170  */
3171 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3172     _nodal_connec(0),_nodal_connec_index(0),
3173     _types(other._types)
3174 {
3175   if(other._nodal_connec)
3176     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCopy);
3177   if(other._nodal_connec_index)
3178     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCopy);
3179 }
3180
3181 MEDCouplingUMesh::~MEDCouplingUMesh()
3182 {
3183   if(_nodal_connec)
3184     _nodal_connec->decrRef();
3185   if(_nodal_connec_index)
3186     _nodal_connec_index->decrRef();
3187 }
3188
3189 /*!
3190  * Recomputes a set of cell types of \a this mesh. For more info see
3191  * \ref MEDCouplingUMeshNodalConnectivity.
3192  */
3193 void MEDCouplingUMesh::computeTypes()
3194 {
3195   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3196 }
3197
3198 /*!
3199  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3200  */
3201 void MEDCouplingUMesh::checkFullyDefined() const
3202 {
3203   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3204     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3205 }
3206
3207 /*!
3208  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3209  */
3210 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3211 {
3212   if(!_nodal_connec_index || !_nodal_connec)
3213     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3214 }
3215
3216 /*!
3217  * Returns a number of cells constituting \a this mesh. 
3218  *  \return int - the number of cells in \a this mesh.
3219  *  \throw If the nodal connectivity of cells is not defined.
3220  */
3221 int MEDCouplingUMesh::getNumberOfCells() const
3222
3223   if(_nodal_connec_index)
3224     return _nodal_connec_index->getNumberOfTuples()-1;
3225   else
3226     if(_mesh_dim==-1)
3227       return 1;
3228     else
3229       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3230 }
3231
3232 /*!
3233  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3234  * mesh. For more info see \ref meshes.
3235  *  \return int - the dimension of \a this mesh.
3236  *  \throw If the mesh dimension is not defined using setMeshDimension().
3237  */
3238 int MEDCouplingUMesh::getMeshDimension() const
3239 {
3240   if(_mesh_dim<-1)
3241     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3242   return _mesh_dim;
3243 }
3244
3245 /*!
3246  * Returns a length of the nodal connectivity array.
3247  * This method is for test reason. Normally the integer returned is not useable by
3248  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3249  *  \return int - the length of the nodal connectivity array.
3250  */
3251 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3252 {
3253   return _nodal_connec->getNbOfElems();
3254 }
3255
3256 /*!
3257  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3258  */
3259 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3260 {
3261   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3262   tinyInfo.push_back(getMeshDimension());
3263   tinyInfo.push_back(getNumberOfCells());
3264   if(_nodal_connec)
3265     tinyInfo.push_back(getNodalConnectivityArrayLen());
3266   else
3267     tinyInfo.push_back(-1);
3268 }
3269
3270 /*!
3271  * First step of unserialization process.
3272  */
3273 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3274 {
3275   return tinyInfo[6]<=0;
3276 }
3277
3278 /*!
3279  * Second step of serialization process.
3280  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3281  * \param a1
3282  * \param a2
3283  * \param littleStrings
3284  */
3285 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3286 {
3287   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3288   if(tinyInfo[5]!=-1)
3289     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3290 }
3291
3292 /*!
3293  * Third and final step of serialization process.
3294  */
3295 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3296 {
3297   MEDCouplingPointSet::serialize(a1,a2);
3298   if(getMeshDimension()>-1)
3299     {
3300       a1=DataArrayInt::New();
3301       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3302       int *ptA1=a1->getPointer();
3303       const int *conn=getNodalConnectivity()->getConstPointer();
3304       const int *index=getNodalConnectivityIndex()->getConstPointer();
3305       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3306       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3307     }
3308   else
3309     a1=0;
3310 }
3311
3312 /*!
3313  * Second and final unserialization process.
3314  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3315  */
3316 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3317 {
3318   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3319   setMeshDimension(tinyInfo[5]);
3320   if(tinyInfo[7]!=-1)
3321     {
3322       // Connectivity
3323       const int *recvBuffer=a1->getConstPointer();
3324       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3325       myConnecIndex->alloc(tinyInfo[6]+1,1);
3326       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3327       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3328       myConnec->alloc(tinyInfo[7],1);
3329       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3330       setConnectivity(myConnec, myConnecIndex);
3331     }
3332 }
3333
3334 /*!
3335  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelfSlice.
3336  * CellIds are given using range specified by a start an end and step.
3337  */
3338 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice(int start, int end, int step) const
3339 {
3340   checkFullyDefined();
3341   int ncell=getNumberOfCells();
3342   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3343   ret->_mesh_dim=_mesh_dim;
3344   ret->setCoords(_coords);
3345   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : ");
3346   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3347   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3348   int work=start;
3349   const int *conn=_nodal_connec->getConstPointer();
3350   const int *connIndex=_nodal_connec_index->getConstPointer();
3351   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3352     {
3353       if(work>=0 && work<ncell)
3354         {
3355           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3356         }
3357       else
3358         {
3359           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3360           throw INTERP_KERNEL::Exception(oss.str().c_str());
3361         }
3362     }
3363   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3364   int *newConnPtr=newConn->getPointer();
3365   std::set<INTERP_KERNEL::NormalizedCellType> types;
3366   work=start;
3367   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3368     {
3369       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3370       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3371     }
3372   ret->setConnectivity(newConn,newConnI,false);
3373   ret->_types=types;
3374   ret->copyTinyInfoFrom(this);
3375   return ret.retn();
3376 }
3377
3378 /*!
3379  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3380  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3381  * The return newly allocated mesh will share the same coordinates as \a this.
3382  */
3383 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3384 {
3385   checkConnectivityFullyDefined();
3386   int ncell=getNumberOfCells();
3387   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3388   ret->_mesh_dim=_mesh_dim;
3389   ret->setCoords(_coords);
3390   std::size_t nbOfElemsRet=std::distance(begin,end);
3391   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3392   connIndexRet[0]=0;
3393   const int *conn=_nodal_connec->getConstPointer();
3394   const int *connIndex=_nodal_connec_index->getConstPointer();
3395   int newNbring=0;
3396   for(const int *work=begin;work!=end;work++,newNbring++)
3397     {
3398       if(*work>=0 && *work<ncell)
3399         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3400       else
3401         {
3402           free(connIndexRet);
3403           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3404           throw INTERP_KERNEL::Exception(oss.str().c_str());
3405         }
3406     }
3407   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3408   int *connRetWork=connRet;
3409   std::set<INTERP_KERNEL::NormalizedCellType> types;
3410   for(const int *work=begin;work!=end;work++)
3411     {
3412       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3413       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3414     }
3415   MCAuto<DataArrayInt> connRetArr=DataArrayInt::New();
3416   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3417   MCAuto<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3418   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3419   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3420   ret->_types=types;
3421   ret->copyTinyInfoFrom(this);
3422   return ret.retn();
3423 }
3424
3425 /*!
3426  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3427  * mesh.<br>
3428  * For 1D cells, the returned field contains lengths.<br>
3429  * For 2D cells, the returned field contains areas.<br>
3430  * For 3D cells, the returned field contains volumes.
3431  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3432  *         orientation, i.e. the volume is always positive.
3433  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3434  *         and one time . The caller is to delete this field using decrRef() as it is no
3435  *         more needed.
3436  */
3437 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3438 {
3439   std::string name="MeasureOfMesh_";
3440   name+=getName();
3441   int nbelem=getNumberOfCells();
3442   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3443   field->setName(name);
3444   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3445   array->alloc(nbelem,1);
3446   double *area_vol=array->getPointer();
3447   field->setArray(array) ; array=0;
3448   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3449   field->synchronizeTimeWithMesh();
3450   if(getMeshDimension()!=-1)
3451     {
3452       int ipt;
3453       INTERP_KERNEL::NormalizedCellType type;
3454       int dim_space=getSpaceDimension();
3455       const double *coords=getCoords()->getConstPointer();
3456       const int *connec=getNodalConnectivity()->getConstPointer();
3457       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3458       for(int iel=0;iel<nbelem;iel++)
3459         {
3460           ipt=connec_index[iel];
3461           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3462           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);
3463         }
3464       if(isAbs)
3465         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3466     }
3467   else
3468     {
3469       area_vol[0]=std::numeric_limits<double>::max();
3470     }
3471   return field.retn();
3472 }
3473
3474 /*!
3475  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3476  * mesh.<br>
3477  * For 1D cells, the returned array contains lengths.<br>
3478  * For 2D cells, the returned array contains areas.<br>
3479  * For 3D cells, the returned array contains volumes.
3480  * This method avoids building explicitly a part of \a this mesh to perform the work.
3481  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3482  *         orientation, i.e. the volume is always positive.
3483  *  \param [in] begin - an array of cell ids of interest.
3484  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3485  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3486  *          delete this array using decrRef() as it is no more needed.
3487  * 
3488  *  \if ENABLE_EXAMPLES
3489  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3490  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3491  *  \endif
3492  *  \sa getMeasureField()
3493  */
3494 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3495 {
3496   std::string name="PartMeasureOfMesh_";
3497   name+=getName();
3498   int nbelem=(int)std::distance(begin,end);
3499   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3500   array->setName(name);
3501   array->alloc(nbelem,1);
3502   double *area_vol=array->getPointer();
3503   if(getMeshDimension()!=-1)
3504     {
3505       int ipt;
3506       INTERP_KERNEL::NormalizedCellType type;
3507       int dim_space=getSpaceDimension();
3508       const double *coords=getCoords()->getConstPointer();
3509       const int *connec=getNodalConnectivity()->getConstPointer();
3510       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3511       for(const int *iel=begin;iel!=end;iel++)
3512         {
3513           ipt=connec_index[*iel];
3514           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3515           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3516         }
3517       if(isAbs)
3518         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3519     }
3520   else
3521     {
3522       area_vol[0]=std::numeric_limits<double>::max();
3523     }
3524   return array.retn();
3525 }
3526
3527 /*!
3528  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3529  * \a this one. The returned field contains the dual cell volume for each corresponding
3530  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3531  *  the dual mesh in P1 sens of \a this.<br>
3532  * For 1D cells, the returned field contains lengths.<br>
3533  * For 2D cells, the returned field contains areas.<br>
3534  * For 3D cells, the returned field contains volumes.
3535  * This method is useful to check "P1*" conservative interpolators.
3536  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3537  *         orientation, i.e. the volume is always positive.
3538  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3539  *          nodes and one time. The caller is to delete this array using decrRef() as
3540  *          it is no more needed.
3541  */
3542 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3543 {
3544   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3545   std::string name="MeasureOnNodeOfMesh_";
3546   name+=getName();
3547   int nbNodes=getNumberOfNodes();
3548   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3549   double cst=1./((double)getMeshDimension()+1.);
3550   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3551   array->alloc(nbNodes,1);
3552   double *valsToFill=array->getPointer();
3553   std::fill(valsToFill,valsToFill+nbNodes,0.);
3554   const double *values=tmp->getArray()->getConstPointer();
3555   MCAuto<DataArrayInt> da=DataArrayInt::New();
3556   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3557   getReverseNodalConnectivity(da,daInd);
3558   const int *daPtr=da->getConstPointer();
3559   const int *daIPtr=daInd->getConstPointer();
3560   for(int i=0;i<nbNodes;i++)
3561     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3562       valsToFill[i]+=cst*values[*cell];
3563   ret->setMesh(this);
3564   ret->setArray(array);
3565   return ret.retn();
3566 }
3567
3568 /*!
3569  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3570  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3571  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3572  * and are normalized.
3573  * <br> \a this can be either 
3574  * - a  2D mesh in 2D or 3D space or 
3575  * - an 1D mesh in 2D space.
3576  * 
3577  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3578  *          cells and one time. The caller is to delete this field using decrRef() as
3579  *          it is no more needed.
3580  *  \throw If the nodal connectivity of cells is not defined.
3581  *  \throw If the coordinates array is not set.
3582  *  \throw If the mesh dimension is not set.
3583  *  \throw If the mesh and space dimension is not as specified above.
3584  */
3585 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3586 {
3587   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3588     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3589   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3590   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3591   int nbOfCells=getNumberOfCells();
3592   int nbComp=getMeshDimension()+1;
3593   array->alloc(nbOfCells,nbComp);
3594   double *vals=array->getPointer();
3595   const int *connI=_nodal_connec_index->getConstPointer();
3596   const int *conn=_nodal_connec->getConstPointer();
3597   const double *coords=_coords->getConstPointer();
3598   if(getMeshDimension()==2)
3599     {
3600       if(getSpaceDimension()==3)
3601         {
3602           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3603           const double *locPtr=loc->getConstPointer();
3604           for(int i=0;i<nbOfCells;i++,vals+=3)
3605             {
3606               int offset=connI[i];
3607               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3608               double n=INTERP_KERNEL::norm<3>(vals);
3609               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3610             }
3611         }
3612       else
3613         {
3614           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3615           const double *isAbsPtr=isAbs->getArray()->begin();
3616           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3617             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3618         }
3619     }
3620   else//meshdimension==1
3621     {
3622       double tmp[2];
3623       for(int i=0;i<nbOfCells;i++)
3624         {
3625           int offset=connI[i];
3626           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3627           double n=INTERP_KERNEL::norm<2>(tmp);
3628           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3629           *vals++=-tmp[1];
3630           *vals++=tmp[0];
3631         }
3632     }
3633   ret->setArray(array);
3634   ret->setMesh(this);
3635   ret->synchronizeTimeWithSupport();
3636   return ret.retn();
3637 }
3638
3639 /*!
3640  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3641  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3642  * and are normalized.
3643  * <br> \a this can be either 
3644  * - a  2D mesh in 2D or 3D space or 
3645  * - an 1D mesh in 2D space.
3646  * 
3647  * This method avoids building explicitly a part of \a this mesh to perform the work.
3648  *  \param [in] begin - an array of cell ids of interest.
3649  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3650  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3651  *          cells and one time. The caller is to delete this field using decrRef() as
3652  *          it is no more needed.
3653  *  \throw If the nodal connectivity of cells is not defined.
3654  *  \throw If the coordinates array is not set.
3655  *  \throw If the mesh dimension is not set.
3656  *  \throw If the mesh and space dimension is not as specified above.
3657  *  \sa buildOrthogonalField()
3658  *
3659  *  \if ENABLE_EXAMPLES
3660  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3661  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3662  *  \endif
3663  */
3664 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3665 {
3666   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3667     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3668   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3669   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3670   std::size_t nbelems=std::distance(begin,end);
3671   int nbComp=getMeshDimension()+1;
3672   array->alloc((int)nbelems,nbComp);
3673   double *vals=array->getPointer();
3674   const int *connI=_nodal_connec_index->getConstPointer();
3675   const int *conn=_nodal_connec->getConstPointer();
3676   const double *coords=_coords->getConstPointer();
3677   if(getMeshDimension()==2)
3678     {
3679       if(getSpaceDimension()==3)
3680         {
3681           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3682           const double *locPtr=loc->getConstPointer();
3683           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3684             {
3685               int offset=connI[*i];
3686               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3687               double n=INTERP_KERNEL::norm<3>(vals);
3688               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3689             }
3690         }
3691       else
3692         {
3693           for(std::size_t i=0;i<nbelems;i++)
3694             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3695         }
3696     }
3697   else//meshdimension==1
3698     {
3699       double tmp[2];
3700       for(const int *i=begin;i!=end;i++)
3701         {
3702           int offset=connI[*i];
3703           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3704           double n=INTERP_KERNEL::norm<2>(tmp);
3705           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3706           *vals++=-tmp[1];
3707           *vals++=tmp[0];
3708         }
3709     }
3710   ret->setArray(array);
3711   ret->setMesh(this);
3712   ret->synchronizeTimeWithSupport();
3713   return ret.retn();
3714 }
3715
3716 /*!
3717  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3718  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3719  * and are \b not normalized.
3720  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3721  *          cells and one time. The caller is to delete this field using decrRef() as
3722  *          it is no more needed.
3723  *  \throw If the nodal connectivity of cells is not defined.
3724  *  \throw If the coordinates array is not set.
3725  *  \throw If \a this->getMeshDimension() != 1.
3726  *  \throw If \a this mesh includes cells of type other than SEG2.
3727  */
3728 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3729 {
3730   if(getMeshDimension()!=1)
3731     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3732   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3733     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3734   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3735   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3736   int nbOfCells=getNumberOfCells();
3737   int spaceDim=getSpaceDimension();
3738   array->alloc(nbOfCells,spaceDim);
3739   double *pt=array->getPointer();
3740   const double *coo=getCoords()->getConstPointer();
3741   std::vector<int> conn;
3742   conn.reserve(2);
3743   for(int i=0;i<nbOfCells;i++)
3744     {
3745       conn.resize(0);
3746       getNodeIdsOfCell(i,conn);
3747       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3748     }
3749   ret->setArray(array);
3750   ret->setMesh(this);
3751   ret->synchronizeTimeWithSupport();
3752   return ret.retn();
3753 }
3754
3755 /*!
3756  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3757  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3758  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3759  * from. If a result face is shared by two 3D cells, then the face in included twice in
3760  * the result mesh.
3761  *  \param [in] origin - 3 components of a point defining location of the plane.
3762  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3763  *         must be greater than 1e-6.
3764  *  \param [in] eps - half-thickness of the plane.
3765  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3766  *         producing correspondent 2D cells. The caller is to delete this array
3767  *         using decrRef() as it is no more needed.
3768  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3769  *         not share the node coordinates array with \a this mesh. The caller is to
3770  *         delete this mesh using decrRef() as it is no more needed.  
3771  *  \throw If the coordinates array is not set.
3772  *  \throw If the nodal connectivity of cells is not defined.
3773  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3774  *  \throw If magnitude of \a vec is less than 1e-6.
3775  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3776  *  \throw If \a this includes quadratic cells.
3777  */
3778 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3779 {
3780   checkFullyDefined();
3781   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3783   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3784   if(candidates->empty())
3785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3786   std::vector<int> nodes;
3787   DataArrayInt *cellIds1D=0;
3788   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3789   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3790   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3791   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3792   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3793   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3794   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3795   revDesc2=0; revDescIndx2=0;
3796   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3797   revDesc1=0; revDescIndx1=0;
3798   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3799   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3800   //
3801   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3802   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3803     cut3DCurve[*it]=-1;
3804   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3805   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3806   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3807                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3808                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3809   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3810   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3811   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3812   if(cellIds2->empty())
3813     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3814   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3815   ret->setCoords(mDesc1->getCoords());
3816   ret->setConnectivity(conn,connI,true);
3817   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3818   return ret.retn();
3819 }
3820
3821 /*!
3822  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3823 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
3824 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3825 the result mesh.
3826  *  \param [in] origin - 3 components of a point defining location of the plane.
3827  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3828  *         must be greater than 1e-6.
3829  *  \param [in] eps - half-thickness of the plane.
3830  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3831  *         producing correspondent segments. The caller is to delete this array
3832  *         using decrRef() as it is no more needed.
3833  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3834  *         mesh in 3D space. This mesh does not share the node coordinates array with
3835  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3836  *         no more needed. 
3837  *  \throw If the coordinates array is not set.
3838  *  \throw If the nodal connectivity of cells is not defined.
3839  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3840  *  \throw If magnitude of \a vec is less than 1e-6.
3841  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3842  *  \throw If \a this includes quadratic cells.
3843  */
3844 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3845 {
3846   checkFullyDefined();
3847   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3848     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3849   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3850   if(candidates->empty())
3851     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3852   std::vector<int> nodes;
3853   DataArrayInt *cellIds1D=0;
3854   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3855   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3856   MCAuto<DataArrayInt> desc1=DataArrayInt::New();
3857   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New();
3858   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New();
3859   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New();
3860   MCAuto<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3861   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3862   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3863   //
3864   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3865   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3866     cut3DCurve[*it]=-1;
3867   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3868   int ncellsSub=subMesh->getNumberOfCells();
3869   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3870   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3871                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3872                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3873   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3874   conn->alloc(0,1);
3875   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3876   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3877   for(int i=0;i<ncellsSub;i++)
3878     {
3879       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3880         {
3881           if(cut3DSurf[i].first!=-2)
3882             {
3883               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3884               connI->pushBackSilent(conn->getNumberOfTuples());
3885               cellIds2->pushBackSilent(i);
3886             }
3887           else
3888             {
3889               int cellId3DSurf=cut3DSurf[i].second;
3890               int offset=nodalI[cellId3DSurf]+1;
3891               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3892               for(int j=0;j<nbOfEdges;j++)
3893                 {
3894                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3895                   connI->pushBackSilent(conn->getNumberOfTuples());
3896                   cellIds2->pushBackSilent(cellId3DSurf);
3897                 }
3898             }
3899         }
3900     }
3901   if(cellIds2->empty())
3902     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3903   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3904   ret->setCoords(mDesc1->getCoords());
3905   ret->setConnectivity(conn,connI,true);
3906   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3907   return ret.retn();
3908 }
3909
3910 /*!
3911  * Finds cells whose bounding boxes intersect a given plane.
3912  *  \param [in] origin - 3 components of a point defining location of the plane.
3913  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3914  *         must be greater than 1e-6.
3915  *  \param [in] eps - half-thickness of the plane.
3916  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3917  *         cells. The caller is to delete this array using decrRef() as it is no more
3918  *         needed.
3919  *  \throw If the coordinates array is not set.
3920  *  \throw If the nodal connectivity of cells is not defined.
3921  *  \throw If \a this->getSpaceDimension() != 3.
3922  *  \throw If magnitude of \a vec is less than 1e-6.
3923  *  \sa buildSlice3D()
3924  */
3925 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3926 {
3927   checkFullyDefined();
3928   if(getSpaceDimension()!=3)
3929     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3930   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3931   if(normm<1e-6)
3932     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3933   double vec2[3];
3934   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3935   double angle=acos(vec[2]/normm);
3936   MCAuto<DataArrayInt> cellIds;
3937   double bbox[6];
3938   if(angle>eps)
3939     {
3940       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3941       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3942       if(normm2/normm>1e-6)
3943         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3944       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3945       mw->setCoords(coo);
3946       mw->getBoundingBox(bbox);
3947       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3948       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3949     }
3950   else
3951     {
3952       getBoundingBox(bbox);
3953       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3954       cellIds=getCellsInBoundingBox(bbox,eps);
3955     }
3956   return cellIds.retn();
3957 }
3958
3959 /*!
3960  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3961  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3962  * No consideration of coordinate is done by this method.
3963  * 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)
3964  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
3965  */
3966 bool MEDCouplingUMesh::isContiguous1D() const
3967 {
3968   if(getMeshDimension()!=1)
3969     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3970   int nbCells=getNumberOfCells();
3971   if(nbCells<1)
3972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3973   const int *connI=_nodal_connec_index->getConstPointer();
3974   const int *conn=_nodal_connec->getConstPointer();
3975   int ref=conn[connI[0]+2];
3976   for(int i=1;i<nbCells;i++)
3977     {
3978       if(conn[connI[i]+1]!=ref)
3979         return false;
3980       ref=conn[connI[i]+2];
3981     }
3982   return true;
3983 }
3984
3985 /*!
3986  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3987  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3988  * \param pt reference point of the line
3989  * \param v normalized director vector of the line
3990  * \param eps max precision before throwing an exception
3991  * \param res output of size this->getNumberOfCells
3992  */
3993 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3994 {
3995   if(getMeshDimension()!=1)
3996     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3997   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3998     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3999   if(getSpaceDimension()!=3)
4000     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4001   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4002   const double *fPtr=f->getArray()->getConstPointer();
4003   double tmp[3];
4004   for(int i=0;i<getNumberOfCells();i++)
4005     {
4006       const double *tmp1=fPtr+3*i;
4007       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4008       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4009       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4010       double n1=INTERP_KERNEL::norm<3>(tmp);
4011       n1/=INTERP_KERNEL::norm<3>(tmp1);
4012       if(n1>eps)
4013         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4014     }
4015   const double *coo=getCoords()->getConstPointer();
4016   for(int i=0;i<getNumberOfNodes();i++)
4017     {
4018       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4019       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4020       res[i]=std::accumulate(tmp,tmp+3,0.);
4021     }
4022 }
4023
4024 /*!
4025  * 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. 
4026  * \a this is expected to be a mesh so that its space dimension is equal to its
4027  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4028  * 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).
4029  *
4030  * 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
4031  * 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).
4032  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4033  *
4034  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4035  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4036  *
4037  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4038  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4039  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4040  * \return the positive value of the distance.
4041  * \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
4042  * dimension - 1.
4043  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4044  */
4045 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4046 {
4047   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4048   if(meshDim!=spaceDim-1)
4049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4050   if(meshDim!=2 && meshDim!=1)
4051     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4052   checkFullyDefined();
4053   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4054     { 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()); }
4055   DataArrayInt *ret1=0;
4056   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4057   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4058   MCAuto<DataArrayInt> ret1Safe(ret1);
4059   cellId=*ret1Safe->begin();
4060   return *ret0->begin();
4061 }
4062
4063 /*!
4064  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4065  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4066  * 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
4067  * 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).
4068  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4069  * 
4070  * \a this is expected to be a mesh so that its space dimension is equal to its
4071  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4072  * 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).
4073  *
4074  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4075  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4076  *
4077  * \param [in] pts the list of points in which each tuple represents a point
4078  * \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.
4079  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4080  * \throw if number of components of \a pts is not equal to the space dimension.
4081  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4082  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4083  */
4084 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4085 {
4086   if(!pts)
4087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4088   pts->checkAllocated();
4089   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4090   if(meshDim!=spaceDim-1)
4091     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4092   if(meshDim!=2 && meshDim!=1)
4093     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4094   if(pts->getNumberOfComponents()!=spaceDim)
4095     {
4096       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4097       throw INTERP_KERNEL::Exception(oss.str().c_str());
4098     }
4099   checkFullyDefined();
4100   int nbCells=getNumberOfCells();
4101   if(nbCells==0)
4102     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4103   int nbOfPts=pts->getNumberOfTuples();
4104   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4105   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4106   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4107   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4108   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4109   const double *bbox(bboxArr->begin());
4110   switch(spaceDim)
4111   {
4112     case 3:
4113       {
4114         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4115         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4116           {
4117             double x=std::numeric_limits<double>::max();
4118             std::vector<int> elems;
4119             myTree.getMinDistanceOfMax(ptsPtr,x);
4120             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4121             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4122           }
4123         break;
4124       }
4125     case 2:
4126       {
4127         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4128         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4129           {
4130             double x=std::numeric_limits<double>::max();
4131             std::vector<int> elems;
4132             myTree.getMinDistanceOfMax(ptsPtr,x);
4133             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4134             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4135           }
4136         break;
4137       }
4138     default:
4139       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4140   }
4141   cellIds=ret1.retn();
4142   return ret0.retn();
4143 }
4144
4145 /// @cond INTERNAL
4146
4147 /*!
4148  * \param [in] pt the start pointer (included) of the coordinates of the point
4149  * \param [in] cellIdsBg the start pointer (included) of cellIds
4150  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4151  * \param [in] nc nodal connectivity
4152  * \param [in] ncI nodal connectivity index
4153  * \param [in,out] ret0 the min distance between \a this and the external input point
4154  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4155  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4156  */
4157 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)
4158 {
4159   cellId=-1;
4160   ret0=std::numeric_limits<double>::max();
4161   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4162     {
4163       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4164       {
4165         case INTERP_KERNEL::NORM_TRI3:
4166           {
4167             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4168             if(tmp<ret0)
4169               { ret0=tmp; cellId=*zeCell; }
4170             break;
4171           }
4172         case INTERP_KERNEL::NORM_QUAD4:
4173         case INTERP_KERNEL::NORM_POLYGON:
4174           {
4175             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4176             if(tmp<ret0)
4177               { ret0=tmp; cellId=*zeCell; }
4178             break;
4179           }
4180         default:
4181           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4182       }
4183     }
4184 }
4185
4186 /*!
4187  * \param [in] pt the start pointer (included) of the coordinates of the point
4188  * \param [in] cellIdsBg the start pointer (included) of cellIds
4189  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4190  * \param [in] nc nodal connectivity
4191  * \param [in] ncI nodal connectivity index
4192  * \param [in,out] ret0 the min distance between \a this and the external input point
4193  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4194  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4195  */
4196 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)
4197 {
4198   cellId=-1;
4199   ret0=std::numeric_limits<double>::max();
4200   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4201     {
4202       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4203       {
4204         case INTERP_KERNEL::NORM_SEG2:
4205           {
4206             std::size_t uselessEntry=0;
4207             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4208             tmp=sqrt(tmp);
4209             if(tmp<ret0)
4210               { ret0=tmp; cellId=*zeCell; }
4211             break;
4212           }
4213         default:
4214           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4215       }
4216     }
4217 }
4218 /// @endcond
4219
4220 /*!
4221  * Finds cells in contact with a ball (i.e. a point with precision). 
4222  * 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.
4223  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4224  *
4225  * \warning This method is suitable if the caller intends to evaluate only one
4226  *          point, for more points getCellsContainingPoints() is recommended as it is
4227  *          faster. 
4228  *  \param [in] pos - array of coordinates of the ball central point.
4229  *  \param [in] eps - ball radius.
4230  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4231  *         if there are no such cells.
4232  *  \throw If the coordinates array is not set.
4233  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4234  */
4235 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4236 {
4237   std::vector<int> elts;
4238   getCellsContainingPoint(pos,eps,elts);
4239   if(elts.empty())
4240     return -1;
4241   return elts.front();
4242 }
4243
4244 /*!
4245  * Finds cells in contact with a ball (i.e. a point with precision).
4246  * 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.
4247  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4248  * \warning This method is suitable if the caller intends to evaluate only one
4249  *          point, for more points getCellsContainingPoints() is recommended as it is
4250  *          faster. 
4251  *  \param [in] pos - array of coordinates of the ball central point.
4252  *  \param [in] eps - ball radius.
4253  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4254  *         before inserting ids.
4255  *  \throw If the coordinates array is not set.
4256  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4257  *
4258  *  \if ENABLE_EXAMPLES
4259  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4260  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4261  *  \endif
4262  */
4263 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4264 {
4265   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4266   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4267   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4268 }
4269
4270 /// @cond INTERNAL
4271
4272 namespace MEDCoupling
4273 {
4274   template<const int SPACEDIMM>
4275   class DummyClsMCUG
4276   {
4277   public:
4278     static const int MY_SPACEDIM=SPACEDIMM;
4279     static const int MY_MESHDIM=8;
4280     typedef int MyConnType;
4281     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4282     // begin
4283     // useless, but for windows compilation ...
4284     const double* getCoordinatesPtr() const { return 0; }
4285     const int* getConnectivityPtr() const { return 0; }
4286     const int* getConnectivityIndexPtr() const { return 0; }
4287     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4288     // end
4289   };
4290
4291   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MCAuto<INTERP_KERNEL::Node>,int>& m)
4292   {
4293     INTERP_KERNEL::Edge *ret(0);
4294     MCAuto<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]));
4295     m[n0]=bg[0]; m[n1]=bg[1];
4296     switch(typ)
4297     {
4298       case INTERP_KERNEL::NORM_SEG2:
4299         {
4300           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4301           break;
4302         }
4303       case INTERP_KERNEL::NORM_SEG3:
4304         {
4305           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4306           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4307           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4308           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4309           bool colinearity(inters.areColinears());
4310           delete e1; delete e2;
4311           if(colinearity)
4312             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4313           else
4314             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4315           break;
4316         }
4317       default:
4318         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4319     }
4320     return ret;
4321   }
4322
4323   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4324   {
4325     INTERP_KERNEL::Edge *ret=0;
4326     switch(typ)
4327     {
4328       case INTERP_KERNEL::NORM_SEG2:
4329         {
4330           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4331           break;
4332         }
4333       case INTERP_KERNEL::NORM_SEG3:
4334         {
4335           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4336           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4337           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4338           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4339           bool colinearity=inters.areColinears();
4340           delete e1; delete e2;
4341           if(colinearity)
4342             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4343           else
4344             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4345           mapp2[bg[2]].second=false;
4346           break;
4347         }
4348       default:
4349         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4350     }
4351     return ret;
4352   }
4353
4354   /*!
4355    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4356    * the global mesh 'mDesc'.
4357    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4358    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4359    */
4360   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4361                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4362   {
4363     mapp.clear();
4364     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.
4365     const double *coo=mDesc->getCoords()->getConstPointer();
4366     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4367     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4368     std::set<int> s;
4369     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4370       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4371     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4372       {
4373         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4374         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4375       }
4376     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4377     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4378       {
4379         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4380         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4381       }
4382     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4383       {
4384         if((*it2).second.second)
4385           mapp[(*it2).second.first]=(*it2).first;
4386         ((*it2).second.first)->decrRef();
4387       }
4388     return ret;
4389   }
4390
4391   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4392   {
4393     if(nodeId>=offset2)
4394       {
4395         int locId=nodeId-offset2;
4396         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4397       }
4398     if(nodeId>=offset1)
4399       {
4400         int locId=nodeId-offset1;
4401         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4402       }
4403     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4404   }
4405
4406   /**
4407    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4408    */
4409   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4410                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4411                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4412   {
4413     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4414       {
4415         int eltId1=abs(*desc1)-1;
4416         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4417           {
4418             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4419             if(it==mappRev.end())
4420               {
4421                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4422                 mapp[node]=*it1;
4423                 mappRev[*it1]=node;
4424               }
4425           }
4426       }
4427   }
4428 }
4429
4430 /// @endcond
4431
4432 template<int SPACEDIM>
4433 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4434                                                    double eps, MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4435 {
4436   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4437   int *eltsIndexPtr(eltsIndex->getPointer());
4438   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4439   const double *bbox(bboxArr->begin());
4440   int nbOfCells=getNumberOfCells();
4441   const int *conn=_nodal_connec->getConstPointer();
4442   const int *connI=_nodal_connec_index->getConstPointer();
4443   double bb[2*SPACEDIM];
4444   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4445   for(int i=0;i<nbOfPoints;i++)
4446     {
4447       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4448       for(int j=0;j<SPACEDIM;j++)
4449         {
4450           bb[2*j]=pos[SPACEDIM*i+j];
4451           bb[2*j+1]=pos[SPACEDIM*i+j];
4452         }
4453       std::vector<int> candidates;
4454       myTree.getIntersectingElems(bb,candidates);
4455       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4456         {
4457           int sz(connI[(*iter)+1]-connI[*iter]-1);
4458           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4459           bool status(false);
4460           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4461             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4462           else
4463             {
4464               if(SPACEDIM!=2)
4465                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4466               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4467               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4468               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4469               INTERP_KERNEL::QuadraticPolygon *pol(0);
4470               for(int j=0;j<sz;j++)
4471                 {
4472                   int nodeId(conn[connI[*iter]+1+j]);
4473                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4474                 }
4475               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4476                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4477               else
4478                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4479               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4480               double a(0.),b(0.),c(0.);
4481               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4482               status=pol->isInOrOut2(n);
4483               delete pol; n->decrRef();
4484             }
4485           if(status)
4486             {
4487               eltsIndexPtr[i+1]++;
4488               elts->pushBackSilent(*iter);
4489             }
4490         }
4491     }
4492 }
4493 /*!
4494  * Finds cells in contact with several balls (i.e. points with precision).
4495  * This method is an extension of getCellContainingPoint() and
4496  * getCellsContainingPoint() for the case of multiple points.
4497  * 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.
4498  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4499  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4500  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4501  *         this->getSpaceDimension() * \a nbOfPoints 
4502  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4503  *  \param [in] eps - radius of balls (i.e. the precision).
4504  *  \param [out] elts - vector returning ids of found cells.
4505  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4506  *         dividing cell ids in \a elts into groups each referring to one
4507  *         point. Its every element (except the last one) is an index pointing to the
4508  *         first id of a group of cells. For example cells in contact with the *i*-th
4509  *         point are described by following range of indices:
4510  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4511  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4512  *         Number of cells in contact with the *i*-th point is
4513  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4514  *  \throw If the coordinates array is not set.
4515  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4516  *
4517  *  \if ENABLE_EXAMPLES
4518  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4519  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4520  *  \endif
4521  */
4522 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4523                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4524 {
4525   int spaceDim=getSpaceDimension();
4526   int mDim=getMeshDimension();
4527   if(spaceDim==3)
4528     {
4529       if(mDim==3)
4530         {
4531           const double *coords=_coords->getConstPointer();
4532           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4533         }
4534       /*else if(mDim==2)
4535         {
4536
4537         }*/
4538       else
4539         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4540     }
4541   else if(spaceDim==2)
4542     {
4543       if(mDim==2)
4544         {
4545           const double *coords=_coords->getConstPointer();
4546           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4547         }
4548       else
4549         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4550     }
4551   else if(spaceDim==1)
4552     {
4553       if(mDim==1)
4554         {
4555           const double *coords=_coords->getConstPointer();
4556           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4557         }
4558       else
4559         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4560     }
4561   else
4562     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4563 }
4564
4565 /*!
4566  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4567  * least two its edges intersect each other anywhere except their extremities. An
4568  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4569  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4570  *         cleared before filling in.
4571  *  \param [in] eps - precision.
4572  *  \throw If \a this->getMeshDimension() != 2.
4573  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4574  */
4575 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4576 {
4577   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4578   if(getMeshDimension()!=2)
4579     throw INTERP_KERNEL::Exception(msg);
4580   int spaceDim=getSpaceDimension();
4581   if(spaceDim!=2 && spaceDim!=3)
4582     throw INTERP_KERNEL::Exception(msg);
4583   const int *conn=_nodal_connec->getConstPointer();
4584   const int *connI=_nodal_connec_index->getConstPointer();
4585   int nbOfCells=getNumberOfCells();
4586   std::vector<double> cell2DinS2;
4587   for(int i=0;i<nbOfCells;i++)
4588     {
4589       int offset=connI[i];
4590       int nbOfNodesForCell=connI[i+1]-offset-1;
4591       if(nbOfNodesForCell<=3)
4592         continue;
4593       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4594       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4595       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4596         cells.push_back(i);
4597       cell2DinS2.clear();
4598     }
4599 }
4600
4601 /*!
4602  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4603  *
4604  * 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.
4605  * 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.
4606  * 
4607  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4608  * This convex envelop is computed using Jarvis march algorithm.
4609  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4610  * 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)
4611  * 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.
4612  *
4613  * \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.
4614  * \sa MEDCouplingUMesh::colinearize2D
4615  */
4616 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4617 {
4618   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4619     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4620   checkFullyDefined();
4621   const double *coords=getCoords()->getConstPointer();
4622   int nbOfCells=getNumberOfCells();
4623   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4624   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4625   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4626   int *workIndexOut=nodalConnecIndexOut->getPointer();
4627   *workIndexOut=0;
4628   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4629   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4630   std::set<INTERP_KERNEL::NormalizedCellType> types;
4631   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4632   isChanged->alloc(0,1);
4633   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4634     {
4635       int pos=nodalConnecOut->getNumberOfTuples();
4636       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4637         isChanged->pushBackSilent(i);
4638       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4639       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4640     }
4641   if(isChanged->empty())
4642     return 0;
4643   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4644   _types=types;
4645   return isChanged.retn();
4646 }
4647
4648 /*!
4649  * This method is \b NOT const because it can modify \a this.
4650  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4651  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4652  * \param policy specifies the type of extrusion chosen:
4653  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4654  *   will be repeated to build each level
4655  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4656  *   the 3 preceding points of the 1D mesh. The center of the arc is the center of rotation for each level, the rotation is done
4657  *   along an axis normal to the plane containing the arc, and finally the angle of rotation is defined by the first two points on the
4658  *   arc.
4659  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4660  */
4661 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4662 {
4663   checkFullyDefined();
4664   mesh1D->checkFullyDefined();
4665   if(!mesh1D->isContiguous1D())
4666     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4667   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4668     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4669   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4670     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4671   if(mesh1D->getMeshDimension()!=1)
4672     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4673   bool isQuad=false;
4674   if(isPresenceOfQuadratic())
4675     {
4676       if(mesh1D->isFullyQuadratic())
4677         isQuad=true;
4678       else
4679         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4680     }
4681   int oldNbOfNodes(getNumberOfNodes());
4682   MCAuto<DataArrayDouble> newCoords;
4683   switch(policy)
4684   {
4685     case 0:
4686       {
4687         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4688         break;
4689       }
4690     case 1:
4691       {
4692         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4693         break;
4694       }
4695     default:
4696       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4697   }
4698   setCoords(newCoords);
4699   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4700   updateTime();
4701   return ret.retn();
4702 }
4703
4704 /*!
4705  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4706  * If it is not the case an exception will be thrown.
4707  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4708  * intersection of plane defined by ('origin','vec').
4709  * This method has one in/out parameter : 'cut3DCurve'.
4710  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4711  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4712  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4713  * This method will throw an exception if \a this contains a non linear segment.
4714  */
4715 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4716 {
4717   checkFullyDefined();
4718   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4720   int ncells=getNumberOfCells();
4721   int nnodes=getNumberOfNodes();
4722   double vec2[3],vec3[3],vec4[3];
4723   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4724   if(normm<1e-6)
4725     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4726   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4727   const int *conn=_nodal_connec->getConstPointer();
4728   const int *connI=_nodal_connec_index->getConstPointer();
4729   const double *coo=_coords->getConstPointer();
4730   std::vector<double> addCoo;
4731   for(int i=0;i<ncells;i++)
4732     {
4733       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4734         {
4735           if(cut3DCurve[i]==-2)
4736             {
4737               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4738               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];
4739               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4740               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4741               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4742                 {
4743                   const double *st2=coo+3*st;
4744                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4745                   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]));
4746                   if(pos>eps && pos<1-eps)
4747                     {
4748                       int nNode=((int)addCoo.size())/3;
4749                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4750                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4751                       cut3DCurve[i]=nnodes+nNode;
4752                     }
4753                 }
4754             }
4755         }
4756       else
4757         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4758     }
4759   if(!addCoo.empty())
4760     {
4761       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4762       MCAuto<DataArrayDouble> coo2=DataArrayDouble::New();
4763       coo2->alloc(newNbOfNodes,3);
4764       double *tmp=coo2->getPointer();
4765       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4766       std::copy(addCoo.begin(),addCoo.end(),tmp);
4767       DataArrayDouble::SetArrayIn(coo2,_coords);
4768     }
4769 }
4770
4771 /*!
4772  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4773  * \param mesh1D is the input 1D mesh used for translation computation.
4774  * \return newCoords new coords filled by this method. 
4775  */
4776 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4777 {
4778   int oldNbOfNodes=getNumberOfNodes();
4779   int nbOf1DCells=mesh1D->getNumberOfCells();
4780   int spaceDim=getSpaceDimension();
4781   DataArrayDouble *ret=DataArrayDouble::New();
4782   std::vector<bool> isQuads;
4783   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4784   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4785   double *retPtr=ret->getPointer();
4786   const double *coords=getCoords()->getConstPointer();
4787   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4788   std::vector<int> v;
4789   std::vector<double> c;
4790   double vec[3];
4791   v.reserve(3);
4792   c.reserve(6);
4793   for(int i=0;i<nbOf1DCells;i++)
4794     {
4795       v.resize(0);
4796       mesh1D->getNodeIdsOfCell(i,v);
4797       c.resize(0);
4798       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4799       mesh1D->getCoordinatesOfNode(v[0],c);
4800       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4801       for(int j=0;j<oldNbOfNodes;j++)
4802         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4803       if(isQuad)
4804         {
4805           c.resize(0);
4806           mesh1D->getCoordinatesOfNode(v[1],c);
4807           mesh1D->getCoordinatesOfNode(v[0],c);
4808           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4809           for(int j=0;j<oldNbOfNodes;j++)
4810             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4811         }
4812     }
4813   ret->copyStringInfoFrom(*getCoords());
4814   return ret;
4815 }
4816
4817 /*!
4818  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4819  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4820  * \return newCoords new coords filled by this method. 
4821  */
4822 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4823 {
4824   if(mesh1D->getSpaceDimension()==2)
4825     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4826   if(mesh1D->getSpaceDimension()==3)
4827     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4828   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4829 }
4830
4831 /*!
4832  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4833  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4834  * \return newCoords new coords filled by this method. 
4835  */
4836 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4837 {
4838   if(isQuad)
4839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4840   int oldNbOfNodes=getNumberOfNodes();
4841   int nbOf1DCells=mesh1D->getNumberOfCells();
4842   if(nbOf1DCells<2)
4843     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4844   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
4845   int nbOfLevsInVec=nbOf1DCells+1;
4846   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4847   double *retPtr=ret->getPointer();
4848   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4849   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4850   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
4851   tmp->setCoords(tmp2);
4852   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4853   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4854   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4855   for(int i=1;i<nbOfLevsInVec;i++)
4856     {
4857       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4858       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4859       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4860       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4861       tmp->translate(vec);
4862       double tmp3[2],radius,alpha,alpha0;
4863       const double *p0=i+1<nbOfLevsInVec?begin:third;
4864       const double *p1=i+1<nbOfLevsInVec?end:begin;
4865       const double *p2=i+1<nbOfLevsInVec?third:end;
4866       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4867       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]);
4868       double angle=acos(cosangle/(radius*radius));
4869       tmp->rotate(end,0,angle);
4870       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4871     }
4872   return ret.retn();
4873 }
4874
4875 /*!
4876  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4877  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4878  * \return newCoords new coords filled by this method. 
4879  */
4880 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4881 {
4882   if(isQuad)
4883     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4884   int oldNbOfNodes=getNumberOfNodes();
4885   int nbOf1DCells=mesh1D->getNumberOfCells();
4886   if(nbOf1DCells<2)
4887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4888   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
4889   int nbOfLevsInVec=nbOf1DCells+1;
4890   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4891   double *retPtr=ret->getPointer();
4892   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4893   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4894   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
4895   tmp->setCoords(tmp2);
4896   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4897   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4898   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4899   for(int i=1;i<nbOfLevsInVec;i++)
4900     {
4901       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4902       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4903       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4904       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4905       tmp->translate(vec);
4906       double tmp3[2],radius,alpha,alpha0;
4907       const double *p0=i+1<nbOfLevsInVec?begin:third;
4908       const double *p1=i+1<nbOfLevsInVec?end:begin;
4909       const double *p2=i+1<nbOfLevsInVec?third:end;
4910       double vecPlane[3]={
4911         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4912         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4913         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4914       };
4915       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4916       if(norm>1.e-7)
4917         {
4918           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4919           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4920           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4921           double s2=norm2;
4922           double c2=cos(asin(s2));
4923           double m[3][3]={
4924             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4925             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4926             {-vec2[1]*s2, vec2[0]*s2, c2}
4927           };
4928           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]};
4929           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]};
4930           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]};
4931           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4932           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]);
4933           double angle=acos(cosangle/(radius*radius));
4934           tmp->rotate(end,vecPlane,angle);
4935         }
4936       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4937     }
4938   return ret.retn();
4939 }
4940
4941 /*!
4942  * This method is private because not easy to use for end user. This method is const contrary to
4943  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4944  * the coords sorted slice by slice.
4945  * \param isQuad specifies presence of quadratic cells.
4946  */
4947 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4948 {
4949   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4950   int nbOf2DCells(getNumberOfCells());
4951   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4952   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4953   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4954   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4955   newConnI->alloc(nbOf3DCells+1,1);
4956   int *newConnIPtr(newConnI->getPointer());
4957   *newConnIPtr++=0;
4958   std::vector<int> newc;
4959   for(int j=0;j<nbOf2DCells;j++)
4960     {
4961       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4962       *newConnIPtr++=(int)newc.size();
4963     }
4964   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4965   int *newConnPtr(newConn->getPointer());
4966   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4967   newConnIPtr=newConnI->getPointer();
4968   for(int iz=0;iz<nbOf1DCells;iz++)
4969     {
4970       if(iz!=0)
4971         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4972       const int *posOfTypeOfCell(newConnIPtr);
4973       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4974         {
4975           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4976           if(icell!=*posOfTypeOfCell)
4977             {
4978               if(*iter!=-1)
4979                 *newConnPtr=(*iter)+iz*deltaPerLev;
4980               else
4981                 *newConnPtr=-1;
4982             }
4983           else
4984             {
4985               *newConnPtr=*iter;
4986               posOfTypeOfCell++;
4987             }
4988         }
4989     }
4990   ret->setConnectivity(newConn,newConnI,true);
4991   ret->setCoords(getCoords());
4992   return ret;
4993 }
4994
4995 /*!
4996  * Checks if \a this mesh is constituted by only quadratic cells.
4997  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4998  *  \throw If the coordinates array is not set.
4999  *  \throw If the nodal connectivity of cells is not defined.
5000  */
5001 bool MEDCouplingUMesh::isFullyQuadratic() const
5002 {
5003   checkFullyDefined();
5004   bool ret=true;
5005   int nbOfCells=getNumberOfCells();
5006   for(int i=0;i<nbOfCells && ret;i++)
5007     {
5008       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5009       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5010       ret=cm.isQuadratic();
5011     }
5012   return ret;
5013 }
5014
5015 /*!
5016  * Checks if \a this mesh includes any quadratic cell.
5017  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5018  *  \throw If the coordinates array is not set.
5019  *  \throw If the nodal connectivity of cells is not defined.
5020  */
5021 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5022 {
5023   checkFullyDefined();
5024   bool ret=false;
5025   int nbOfCells=getNumberOfCells();
5026   for(int i=0;i<nbOfCells && !ret;i++)
5027     {
5028       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5029       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5030       ret=cm.isQuadratic();
5031     }
5032   return ret;
5033 }
5034
5035 /*!
5036  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5037  * this mesh, it remains unchanged.
5038  *  \throw If the coordinates array is not set.
5039  *  \throw If the nodal connectivity of cells is not defined.
5040  */
5041 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5042 {
5043   checkFullyDefined();
5044   int nbOfCells=getNumberOfCells();
5045   int delta=0;
5046   const int *iciptr=_nodal_connec_index->getConstPointer();
5047   for(int i=0;i<nbOfCells;i++)
5048     {
5049       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5050       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5051       if(cm.isQuadratic())
5052         {
5053           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5054           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5055           if(!cml.isDynamic())
5056             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5057           else
5058             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5059         }
5060     }
5061   if(delta==0)
5062     return ;
5063   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5064   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5065   const int *icptr=_nodal_connec->getConstPointer();
5066   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
5067   newConnI->alloc(nbOfCells+1,1);
5068   int *ocptr=newConn->getPointer();
5069   int *ociptr=newConnI->getPointer();
5070   *ociptr=0;
5071   _types.clear();
5072   for(int i=0;i<nbOfCells;i++,ociptr++)
5073     {
5074       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5075       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5076       if(!cm.isQuadratic())
5077         {
5078           _types.insert(type);
5079           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5080           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5081         }
5082       else
5083         {
5084           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5085           _types.insert(typel);
5086           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5087           int newNbOfNodes=cml.getNumberOfNodes();
5088           if(cml.isDynamic())
5089             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5090           *ocptr++=(int)typel;
5091           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5092           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5093         }
5094     }
5095   setConnectivity(newConn,newConnI,false);
5096 }
5097
5098 /*!
5099  * This method converts all linear cell in \a this to quadratic one.
5100  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5101  * 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)
5102  * 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.
5103  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5104  * end of the existing coordinates.
5105  * 
5106  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5107  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5108  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5109  * 
5110  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5111  *
5112  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5113  */
5114 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5115 {
5116   DataArrayInt *conn=0,*connI=0;
5117   DataArrayDouble *coords=0;
5118   std::set<INTERP_KERNEL::NormalizedCellType> types;
5119   checkFullyDefined();
5120   MCAuto<DataArrayInt> ret,connSafe,connISafe;
5121   MCAuto<DataArrayDouble> coordsSafe;
5122   int meshDim=getMeshDimension();
5123   switch(conversionType)
5124   {
5125     case 0:
5126       switch(meshDim)
5127       {
5128         case 1:
5129           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5130           connSafe=conn; connISafe=connI; coordsSafe=coords;
5131           break;
5132         case 2:
5133           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5134           connSafe=conn; connISafe=connI; coordsSafe=coords;
5135           break;
5136         case 3:
5137           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5138           connSafe=conn; connISafe=connI; coordsSafe=coords;
5139           break;
5140         default:
5141           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5142       }
5143       break;
5144         case 1:
5145           {
5146             switch(meshDim)
5147             {
5148               case 1:
5149                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5150                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5151                 break;
5152               case 2:
5153                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5154                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5155                 break;
5156               case 3:
5157                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5158                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5159                 break;
5160               default:
5161                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5162             }
5163             break;
5164           }
5165         default:
5166           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5167   }
5168   setConnectivity(connSafe,connISafe,false);
5169   _types=types;
5170   setCoords(coordsSafe);
5171   return ret.retn();
5172 }
5173
5174 /*!
5175  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5176  * so that the number of cells remains the same. Quadratic faces are converted to
5177  * polygons. This method works only for 2D meshes in
5178  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5179  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5180  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5181  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5182  *         a polylinized edge constituting the input polygon.
5183  *  \throw If the coordinates array is not set.
5184  *  \throw If the nodal connectivity of cells is not defined.
5185  *  \throw If \a this->getMeshDimension() != 2.
5186  *  \throw If \a this->getSpaceDimension() != 2.
5187  */
5188 void MEDCouplingUMesh::tessellate2D(double eps)
5189 {
5190   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
5191   if(spaceDim!=2)
5192     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
5193   switch(meshDim)
5194     {
5195     case 1:
5196       return tessellate2DCurveInternal(eps);
5197     case 2:
5198       return tessellate2DInternal(eps);
5199     default:
5200       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
5201     }
5202 }
5203 /*!
5204  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5205  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5206  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5207  *         a sub-divided edge.
5208  *  \throw If the coordinates array is not set.
5209  *  \throw If the nodal connectivity of cells is not defined.
5210  *  \throw If \a this->getMeshDimension() != 1.
5211  *  \throw If \a this->getSpaceDimension() != 2.
5212  */
5213
5214 #if 0
5215 /*!
5216  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5217  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5218  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5219  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5220  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5221  * This method can be seen as the opposite method of colinearize2D.
5222  * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end
5223  * to avoid to modify the numbering of existing nodes.
5224  *
5225  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5226  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5227  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5228  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5229  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5230  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5231  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5232  *
5233  * \sa buildDescendingConnectivity2
5234  */
5235 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5236                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5237 {
5238   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5239     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5240   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5241   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5242     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5243   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5244     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5245   //DataArrayInt *out0(0),*outi0(0);
5246   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5247   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
5248   //out0s=out0s->buildUnique(); out0s->sort(true);
5249 }
5250 #endif
5251
5252 /*!
5253  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5254  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5255  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5256  */
5257 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5258 {
5259   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5260   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5261   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5262   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5263   int nbOfCells=getNumberOfCells();
5264   int nbOfNodes=getNumberOfNodes();
5265   const int *cPtr=_nodal_connec->getConstPointer();
5266   const int *icPtr=_nodal_connec_index->getConstPointer();
5267   int lastVal=0,offset=nbOfNodes;
5268   for(int i=0;i<nbOfCells;i++,icPtr++)
5269     {
5270       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5271       if(type==INTERP_KERNEL::NORM_SEG2)
5272         {
5273           types.insert(INTERP_KERNEL::NORM_SEG3);
5274           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5275           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5276           newConn->pushBackSilent(offset++);
5277           lastVal+=4;
5278           newConnI->pushBackSilent(lastVal);
5279           ret->pushBackSilent(i);
5280         }
5281       else
5282         {
5283           types.insert(type);
5284           lastVal+=(icPtr[1]-icPtr[0]);
5285           newConnI->pushBackSilent(lastVal);
5286           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5287         }
5288     }
5289   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5290   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5291   return ret.retn();
5292 }
5293
5294 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
5295 {
5296   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5297   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5298   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5299   //
5300   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5301   DataArrayInt *conn1D=0,*conn1DI=0;
5302   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5303   DataArrayDouble *coordsTmp=0;
5304   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5305   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5306   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5307   const int *c1DPtr=conn1D->begin();
5308   const int *c1DIPtr=conn1DI->begin();
5309   int nbOfCells=getNumberOfCells();
5310   const int *cPtr=_nodal_connec->getConstPointer();
5311   const int *icPtr=_nodal_connec_index->getConstPointer();
5312   int lastVal=0;
5313   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5314     {
5315       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5316       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5317       if(!cm.isQuadratic())
5318         {
5319           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5320           types.insert(typ2); newConn->pushBackSilent(typ2);
5321           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5322           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5323             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5324           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5325           newConnI->pushBackSilent(lastVal);
5326           ret->pushBackSilent(i);
5327         }
5328       else
5329         {
5330           types.insert(typ);
5331           lastVal+=(icPtr[1]-icPtr[0]);
5332           newConnI->pushBackSilent(lastVal);
5333           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5334         }
5335     }
5336   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5337   return ret.retn();
5338 }
5339
5340 /*!
5341  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5342  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5343  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5344  */
5345 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5346 {
5347   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5348   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5349   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5350 }
5351
5352 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5353 {
5354   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5355   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5356   //
5357   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5358   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5359   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5360   //
5361   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5362   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5363   DataArrayInt *conn1D=0,*conn1DI=0;
5364   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5365   DataArrayDouble *coordsTmp=0;
5366   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5367   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5368   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5369   const int *c1DPtr=conn1D->begin();
5370   const int *c1DIPtr=conn1DI->begin();
5371   int nbOfCells=getNumberOfCells();
5372   const int *cPtr=_nodal_connec->getConstPointer();
5373   const int *icPtr=_nodal_connec_index->getConstPointer();
5374   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5375   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5376     {
5377       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5378       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5379       if(!cm.isQuadratic())
5380         {
5381           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5382           types.insert(typ2); newConn->pushBackSilent(typ2);
5383           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5384           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5385             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5386           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5387           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5388           newConnI->pushBackSilent(lastVal);
5389           ret->pushBackSilent(i);
5390         }
5391       else
5392         {
5393           types.insert(typ);
5394           lastVal+=(icPtr[1]-icPtr[0]);
5395           newConnI->pushBackSilent(lastVal);
5396           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5397         }
5398     }
5399   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5400   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5401   return ret.retn();
5402 }
5403
5404 /*!
5405  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5406  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5407  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5408  */
5409 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5410 {
5411   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5412   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5413   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5414 }
5415
5416 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5417 {
5418   MCAuto<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5419   MCAuto<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5420   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5421   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5422   //
5423   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5424   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5425   MCAuto<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5426   //
5427   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5428   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5429   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5430   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5431   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5432   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5433   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5434   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5435   MCAuto<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5436   MCAuto<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5437   MCAuto<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5438   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5439   int nbOfCells=getNumberOfCells();
5440   const int *cPtr=_nodal_connec->getConstPointer();
5441   const int *icPtr=_nodal_connec_index->getConstPointer();
5442   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5443   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5444     {
5445       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5446       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5447       if(!cm.isQuadratic())
5448         {
5449           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5450           if(typ2==INTERP_KERNEL::NORM_ERROR)
5451             {
5452               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5453               throw INTERP_KERNEL::Exception(oss.str().c_str());
5454             }
5455           types.insert(typ2); newConn->pushBackSilent(typ2);
5456           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5457           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5458             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5459           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5460             {
5461               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5462               int tmpPos=newConn->getNumberOfTuples();
5463               newConn->pushBackSilent(nodeId2);
5464               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5465             }
5466           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5467           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5468           newConnI->pushBackSilent(lastVal);
5469           ret->pushBackSilent(i);
5470         }
5471       else
5472         {
5473           types.insert(typ);
5474           lastVal+=(icPtr[1]-icPtr[0]);
5475           newConnI->pushBackSilent(lastVal);
5476           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5477         }
5478     }
5479   MCAuto<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5480   MCAuto<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5481   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5482   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5483   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5484   int *c=newConn->getPointer();
5485   const int *cI(newConnI->begin());
5486   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5487     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5488   offset=coordsTmp2Safe->getNumberOfTuples();
5489   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5490     c[cI[(*elt)+1]-1]+=offset;
5491   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5492   return ret.retn();
5493 }
5494
5495 /*!
5496  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5497  * In addition, returns an array mapping new cells to old ones. <br>
5498  * This method typically increases the number of cells in \a this mesh
5499  * but the number of nodes remains \b unchanged.
5500  * That's why the 3D splitting policies
5501  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5502  *  \param [in] policy - specifies a pattern used for splitting.
5503  * The semantic of \a policy is:
5504  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5505  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5506  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5507  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5508  *
5509  *
5510  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5511  *          an id of old cell producing it. The caller is to delete this array using
5512  *         decrRef() as it is no more needed.
5513  *
5514  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5515  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5516  *          and \a this->getMeshDimension() != 3. 
5517  *  \throw If \a policy is not one of the four discussed above.
5518  *  \throw If the nodal connectivity of cells is not defined.
5519  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5520  */
5521 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5522 {
5523   switch(policy)
5524   {
5525     case 0:
5526       return simplexizePol0();
5527     case 1:
5528       return simplexizePol1();
5529     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5530         return simplexizePlanarFace5();
5531     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5532         return simplexizePlanarFace6();
5533     default:
5534       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)");
5535   }
5536 }
5537
5538 /*!
5539  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5540  * - 1D: INTERP_KERNEL::NORM_SEG2
5541  * - 2D: INTERP_KERNEL::NORM_TRI3
5542  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5543  *
5544  * This method is useful for users that need to use P1 field services as
5545  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5546  * All these methods need mesh support containing only simplex cells.
5547  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5548  *  \throw If the coordinates array is not set.
5549  *  \throw If the nodal connectivity of cells is not defined.
5550  *  \throw If \a this->getMeshDimension() < 1.
5551  */
5552 bool MEDCouplingUMesh::areOnlySimplexCells() const
5553 {
5554   checkFullyDefined();
5555   int mdim=getMeshDimension();
5556   if(mdim<1 || mdim>3)
5557     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5558   int nbCells=getNumberOfCells();
5559   const int *conn=_nodal_connec->getConstPointer();
5560   const int *connI=_nodal_connec_index->getConstPointer();
5561   for(int i=0;i<nbCells;i++)
5562     {
5563       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5564       if(!cm.isSimplex())
5565         return false;
5566     }
5567   return true;
5568 }
5569
5570 /*!
5571  * This method implements policy 0 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5572  */
5573 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5574 {
5575   checkConnectivityFullyDefined();
5576   if(getMeshDimension()!=2)
5577     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5578   int nbOfCells=getNumberOfCells();
5579   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5580   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5581   ret->alloc(nbOfCells+nbOfCutCells,1);
5582   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5583   int *retPt=ret->getPointer();
5584   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5585   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5586   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5587   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5588   int *pt=newConn->getPointer();
5589   int *ptI=newConnI->getPointer();
5590   ptI[0]=0;
5591   const int *oldc=_nodal_connec->getConstPointer();
5592   const int *ci=_nodal_connec_index->getConstPointer();
5593   for(int i=0;i<nbOfCells;i++,ci++)
5594     {
5595       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5596         {
5597           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5598             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5599           pt=std::copy(tmp,tmp+8,pt);
5600           ptI[1]=ptI[0]+4;
5601           ptI[2]=ptI[0]+8;
5602           *retPt++=i;
5603           *retPt++=i;
5604           ptI+=2;
5605         }
5606       else
5607         {
5608           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5609           ptI[1]=ptI[0]+ci[1]-ci[0];
5610           ptI++;
5611           *retPt++=i;
5612         }
5613     }
5614   _nodal_connec->decrRef();
5615   _nodal_connec=newConn.retn();
5616   _nodal_connec_index->decrRef();
5617   _nodal_connec_index=newConnI.retn();
5618   computeTypes();
5619   updateTime();
5620   return ret.retn();
5621 }
5622
5623 /*!
5624  * This method implements policy 1 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5625  */
5626 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5627 {
5628   checkConnectivityFullyDefined();
5629   if(getMeshDimension()!=2)
5630     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5631   int nbOfCells=getNumberOfCells();
5632   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5633   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5634   ret->alloc(nbOfCells+nbOfCutCells,1);
5635   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5636   int *retPt=ret->getPointer();
5637   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5638   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5639   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5640   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5641   int *pt=newConn->getPointer();
5642   int *ptI=newConnI->getPointer();
5643   ptI[0]=0;
5644   const int *oldc=_nodal_connec->getConstPointer();
5645   const int *ci=_nodal_connec_index->getConstPointer();
5646   for(int i=0;i<nbOfCells;i++,ci++)
5647     {
5648       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5649         {
5650           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5651             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5652           pt=std::copy(tmp,tmp+8,pt);
5653           ptI[1]=ptI[0]+4;
5654           ptI[2]=ptI[0]+8;
5655           *retPt++=i;
5656           *retPt++=i;
5657           ptI+=2;
5658         }
5659       else
5660         {
5661           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5662           ptI[1]=ptI[0]+ci[1]-ci[0];
5663           ptI++;
5664           *retPt++=i;
5665         }
5666     }
5667   _nodal_connec->decrRef();
5668   _nodal_connec=newConn.retn();
5669   _nodal_connec_index->decrRef();
5670   _nodal_connec_index=newConnI.retn();
5671   computeTypes();
5672   updateTime();
5673   return ret.retn();
5674 }
5675
5676 /*!
5677  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5678  */
5679 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5680 {
5681   checkConnectivityFullyDefined();
5682   if(getMeshDimension()!=3)
5683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5684   int nbOfCells=getNumberOfCells();
5685   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5686   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5687   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5688   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5689   int *retPt=ret->getPointer();
5690   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5691   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5692   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5693   newConn->alloc(getNodalConnectivityArrayLen()+16*nbOfCutCells,1);//21
5694   int *pt=newConn->getPointer();
5695   int *ptI=newConnI->getPointer();
5696   ptI[0]=0;
5697   const int *oldc=_nodal_connec->getConstPointer();
5698   const int *ci=_nodal_connec_index->getConstPointer();
5699   for(int i=0;i<nbOfCells;i++,ci++)
5700     {
5701       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5702         {
5703           for(int j=0;j<5;j++,pt+=5,ptI++)
5704             {
5705               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5706               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];
5707               *retPt++=i;
5708               ptI[1]=ptI[0]+5;
5709             }
5710         }
5711       else
5712         {
5713           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5714           ptI[1]=ptI[0]+ci[1]-ci[0];
5715           ptI++;
5716           *retPt++=i;
5717         }
5718     }
5719   _nodal_connec->decrRef();
5720   _nodal_connec=newConn.retn();
5721   _nodal_connec_index->decrRef();
5722   _nodal_connec_index=newConnI.retn();
5723   computeTypes();
5724   updateTime();
5725   return ret.retn();
5726 }
5727
5728 /*!
5729  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5730  */
5731 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5732 {
5733   checkConnectivityFullyDefined();
5734   if(getMeshDimension()!=3)
5735     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5736   int nbOfCells=getNumberOfCells();
5737   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5738   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5739   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5740   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5741   int *retPt=ret->getPointer();
5742   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5743   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5744   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5745   newConn->alloc(getNodalConnectivityArrayLen()+21*nbOfCutCells,1);
5746   int *pt=newConn->getPointer();
5747   int *ptI=newConnI->getPointer();
5748   ptI[0]=0;
5749   const int *oldc=_nodal_connec->getConstPointer();
5750   const int *ci=_nodal_connec_index->getConstPointer();
5751   for(int i=0;i<nbOfCells;i++,ci++)
5752     {
5753       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5754         {
5755           for(int j=0;j<6;j++,pt+=5,ptI++)
5756             {
5757               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5758               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];
5759               *retPt++=i;
5760               ptI[1]=ptI[0]+5;
5761             }
5762         }
5763       else
5764         {
5765           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5766           ptI[1]=ptI[0]+ci[1]-ci[0];
5767           ptI++;
5768           *retPt++=i;
5769         }
5770     }
5771   _nodal_connec->decrRef();
5772   _nodal_connec=newConn.retn();
5773   _nodal_connec_index->decrRef();
5774   _nodal_connec_index=newConnI.retn();
5775   computeTypes();
5776   updateTime();
5777   return ret.retn();
5778 }
5779
5780 /*!
5781  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5782  * so that the number of cells remains the same. Quadratic faces are converted to
5783  * polygons. This method works only for 2D meshes in
5784  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5785  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5786  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5787  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5788  *         a polylinized edge constituting the input polygon.
5789  *  \throw If the coordinates array is not set.
5790  *  \throw If the nodal connectivity of cells is not defined.
5791  *  \throw If \a this->getMeshDimension() != 2.
5792  *  \throw If \a this->getSpaceDimension() != 2.
5793  */
5794 void MEDCouplingUMesh::tessellate2DInternal(double eps)
5795 {
5796   checkFullyDefined();
5797   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5798     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5799   double epsa=fabs(eps);
5800   if(epsa<std::numeric_limits<double>::min())
5801     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5802   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
5803   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
5804   revDesc1=0; revDescIndx1=0;
5805   mDesc->tessellate2D(eps);
5806   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5807   setCoords(mDesc->getCoords());
5808 }
5809
5810 /*!
5811  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5812  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5813  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5814  *         a sub-divided edge.
5815  *  \throw If the coordinates array is not set.
5816  *  \throw If the nodal connectivity of cells is not defined.
5817  *  \throw If \a this->getMeshDimension() != 1.
5818  *  \throw If \a this->getSpaceDimension() != 2.
5819  */
5820 void MEDCouplingUMesh::tessellate2DCurveInternal(double eps)
5821 {
5822   checkFullyDefined();
5823   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5825   double epsa=fabs(eps);
5826   if(epsa<std::numeric_limits<double>::min())
5827     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5828   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5829   int nbCells=getNumberOfCells();
5830   int nbNodes=getNumberOfNodes();
5831   const int *conn=_nodal_connec->getConstPointer();
5832   const int *connI=_nodal_connec_index->getConstPointer();
5833   const double *coords=_coords->getConstPointer();
5834   std::vector<double> addCoo;
5835   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5836   MCAuto<DataArrayInt> newConnI(DataArrayInt::New());
5837   newConnI->alloc(nbCells+1,1);
5838   int *newConnIPtr=newConnI->getPointer();
5839   *newConnIPtr=0;
5840   int tmp1[3];
5841   INTERP_KERNEL::Node *tmp2[3];
5842   std::set<INTERP_KERNEL::NormalizedCellType> types;
5843   for(int i=0;i<nbCells;i++,newConnIPtr++)
5844     {
5845       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5846       if(cm.isQuadratic())
5847         {//assert(connI[i+1]-connI[i]-1==3)
5848           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5849           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5850           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5851           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5852           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5853           if(eac)
5854             {
5855               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5856               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5857               delete eac;
5858               newConnIPtr[1]=(int)newConn.size();
5859             }
5860           else
5861             {
5862               types.insert(INTERP_KERNEL::NORM_SEG2);
5863               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5864               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5865               newConnIPtr[1]=newConnIPtr[0]+3;
5866             }
5867         }
5868       else
5869         {
5870           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5871           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5872           newConnIPtr[1]=newConnIPtr[0]+3;
5873         }
5874     }
5875   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5876     return ;
5877   _types=types;
5878   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5879   MCAuto<DataArrayInt> newConnArr=DataArrayInt::New();
5880   newConnArr->alloc((int)newConn.size(),1);
5881   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5882   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5883   MCAuto<DataArrayDouble> newCoords=DataArrayDouble::New();
5884   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5885   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5886   std::copy(addCoo.begin(),addCoo.end(),work);
5887   DataArrayDouble::SetArrayIn(newCoords,_coords);
5888   updateTime();
5889 }
5890
5891 /*!
5892  * 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.
5893  * This method completly ignore coordinates.
5894  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5895  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5896  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5897  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5898  */
5899 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5900 {
5901   checkFullyDefined();
5902   if(getMeshDimension()!=2)
5903     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5904   int nbOfCells=getNumberOfCells();
5905   int *connI=_nodal_connec_index->getPointer();
5906   int newConnLgth=0;
5907   for(int i=0;i<nbOfCells;i++,connI++)
5908     {
5909       int offset=descIndex[i];
5910       int nbOfEdges=descIndex[i+1]-offset;
5911       //
5912       bool ddirect=desc[offset+nbOfEdges-1]>0;
5913       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5914       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5915       for(int j=0;j<nbOfEdges;j++)
5916         {
5917           bool direct=desc[offset+j]>0;
5918           int edgeId=std::abs(desc[offset+j])-1;
5919           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5920             {
5921               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5922               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5923               int ref2=direct?id1:id2;
5924               if(ref==ref2)
5925                 {
5926                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5927                   newConnLgth+=nbOfSubNodes-1;
5928                   ref=direct?id2:id1;
5929                 }
5930               else
5931                 {
5932                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5933                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5934                 }
5935             }
5936           else
5937             {
5938               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5939             }
5940         }
5941       newConnLgth++;//+1 is for cell type
5942       connI[1]=newConnLgth;
5943     }
5944   //
5945   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5946   newConn->alloc(newConnLgth,1);
5947   int *work=newConn->getPointer();
5948   for(int i=0;i<nbOfCells;i++)
5949     {
5950       *work++=INTERP_KERNEL::NORM_POLYGON;
5951       int offset=descIndex[i];
5952       int nbOfEdges=descIndex[i+1]-offset;
5953       for(int j=0;j<nbOfEdges;j++)
5954         {
5955           bool direct=desc[offset+j]>0;
5956           int edgeId=std::abs(desc[offset+j])-1;
5957           if(direct)
5958             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5959           else
5960             {
5961               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5962               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5963               work=std::copy(it,it+nbOfSubNodes-1,work);
5964             }
5965         }
5966     }
5967   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5968   _types.clear();
5969   if(nbOfCells>0)
5970     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5971 }
5972
5973 /*!
5974  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5975  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5976  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5977  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5978  * so it can be useful to call mergeNodes() before calling this method.
5979  *  \throw If \a this->getMeshDimension() <= 1.
5980  *  \throw If the coordinates array is not set.
5981  *  \throw If the nodal connectivity of cells is not defined.
5982  */
5983 void MEDCouplingUMesh::convertDegeneratedCells()
5984 {
5985   checkFullyDefined();
5986   if(getMeshDimension()<=1)
5987     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5988   int nbOfCells=getNumberOfCells();
5989   if(nbOfCells<1)
5990     return ;
5991   int initMeshLgth=getNodalConnectivityArrayLen();
5992   int *conn=_nodal_connec->getPointer();
5993   int *index=_nodal_connec_index->getPointer();
5994   int posOfCurCell=0;
5995   int newPos=0;
5996   int lgthOfCurCell;
5997   for(int i=0;i<nbOfCells;i++)
5998     {
5999       lgthOfCurCell=index[i+1]-posOfCurCell;
6000       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
6001       int newLgth;
6002       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
6003                                                                                                      conn+newPos+1,newLgth);
6004       conn[newPos]=newType;
6005       newPos+=newLgth+1;
6006       posOfCurCell=index[i+1];
6007       index[i+1]=newPos;
6008     }
6009   if(newPos!=initMeshLgth)
6010     _nodal_connec->reAlloc(newPos);
6011   computeTypes();
6012 }
6013
6014 /*!
6015  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6016  * A cell is considered to be oriented correctly if an angle between its
6017  * normal vector and a given vector is less than \c PI / \c 2.
6018  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6019  *         cells. 
6020  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6021  *         checked.
6022  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6023  *         is not cleared before filling in.
6024  *  \throw If \a this->getMeshDimension() != 2.
6025  *  \throw If \a this->getSpaceDimension() != 3.
6026  *
6027  *  \if ENABLE_EXAMPLES
6028  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6029  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6030  *  \endif
6031  */
6032 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6033 {
6034   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6035     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6036   int nbOfCells=getNumberOfCells();
6037   const int *conn=_nodal_connec->getConstPointer();
6038   const int *connI=_nodal_connec_index->getConstPointer();
6039   const double *coordsPtr=_coords->getConstPointer();
6040   for(int i=0;i<nbOfCells;i++)
6041     {
6042       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6043       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6044         {
6045           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6046           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6047             cells.push_back(i);
6048         }
6049     }
6050 }
6051
6052 /*!
6053  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6054  * considered to be oriented correctly if an angle between its normal vector and a
6055  * given vector is less than \c PI / \c 2. 
6056  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6057  *         cells. 
6058  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6059  *         checked.
6060  *  \throw If \a this->getMeshDimension() != 2.
6061  *  \throw If \a this->getSpaceDimension() != 3.
6062  *
6063  *  \if ENABLE_EXAMPLES
6064  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6065  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6066  *  \endif
6067  *
6068  *  \sa changeOrientationOfCells
6069  */
6070 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6071 {
6072   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6073     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6074   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6075   const int *connI(_nodal_connec_index->getConstPointer());
6076   const double *coordsPtr(_coords->getConstPointer());
6077   bool isModified(false);
6078   for(int i=0;i<nbOfCells;i++)
6079     {
6080       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6081       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6082         {
6083           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6084           bool isQuadratic(cm.isQuadratic());
6085           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6086             {
6087               isModified=true;
6088               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6089             }
6090         }
6091     }
6092   if(isModified)
6093     _nodal_connec->declareAsNew();
6094   updateTime();
6095 }
6096
6097 /*!
6098  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6099  *
6100  * \sa orientCorrectly2DCells
6101  */
6102 void MEDCouplingUMesh::changeOrientationOfCells()
6103 {
6104   int mdim(getMeshDimension());
6105   if(mdim!=2 && mdim!=1)
6106     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6107   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6108   const int *connI(_nodal_connec_index->getConstPointer());
6109   if(mdim==2)
6110     {//2D
6111       for(int i=0;i<nbOfCells;i++)
6112         {
6113           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6114           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6115           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6116         }
6117     }
6118   else
6119     {//1D
6120       for(int i=0;i<nbOfCells;i++)
6121         {
6122           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6123           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6124           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6125         }
6126     }
6127 }
6128
6129 /*!
6130  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6131  * oriented facets. The normal vector of the facet should point out of the cell.
6132  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6133  *         is not cleared before filling in.
6134  *  \throw If \a this->getMeshDimension() != 3.
6135  *  \throw If \a this->getSpaceDimension() != 3.
6136  *  \throw If the coordinates array is not set.
6137  *  \throw If the nodal connectivity of cells is not defined.
6138  *
6139  *  \if ENABLE_EXAMPLES
6140  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6141  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6142  *  \endif
6143  */
6144 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6145 {
6146   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6147     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6148   int nbOfCells=getNumberOfCells();
6149   const int *conn=_nodal_connec->getConstPointer();
6150   const int *connI=_nodal_connec_index->getConstPointer();
6151   const double *coordsPtr=_coords->getConstPointer();
6152   for(int i=0;i<nbOfCells;i++)
6153     {
6154       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6155       if(type==INTERP_KERNEL::NORM_POLYHED)
6156         {
6157           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6158             cells.push_back(i);
6159         }
6160     }
6161 }
6162
6163 /*!
6164  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6165  * out of the cell. 
6166  *  \throw If \a this->getMeshDimension() != 3.
6167  *  \throw If \a this->getSpaceDimension() != 3.
6168  *  \throw If the coordinates array is not set.
6169  *  \throw If the nodal connectivity of cells is not defined.
6170  *  \throw If the reparation fails.
6171  *
6172  *  \if ENABLE_EXAMPLES
6173  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6174  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6175  *  \endif
6176  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6177  */
6178 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6179 {
6180   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6181     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6182   int nbOfCells=getNumberOfCells();
6183   int *conn=_nodal_connec->getPointer();
6184   const int *connI=_nodal_connec_index->getConstPointer();
6185   const double *coordsPtr=_coords->getConstPointer();
6186   for(int i=0;i<nbOfCells;i++)
6187     {
6188       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6189       if(type==INTERP_KERNEL::NORM_POLYHED)
6190         {
6191           try
6192           {
6193               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6194                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6195           }
6196           catch(INTERP_KERNEL::Exception& e)
6197           {
6198               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6199               throw INTERP_KERNEL::Exception(oss.str().c_str());
6200           }
6201         }
6202     }
6203   updateTime();
6204 }
6205
6206 /*!
6207  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6208  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6209  * according to which the first facet of the cell should be oriented to have the normal vector
6210  * pointing out of cell.
6211  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6212  *         cells. The caller is to delete this array using decrRef() as it is no more
6213  *         needed. 
6214  *  \throw If \a this->getMeshDimension() != 3.
6215  *  \throw If \a this->getSpaceDimension() != 3.
6216  *  \throw If the coordinates array is not set.
6217  *  \throw If the nodal connectivity of cells is not defined.
6218  *
6219  *  \if ENABLE_EXAMPLES
6220  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6221  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6222  *  \endif
6223  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6224  */
6225 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6226 {
6227   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6228   if(getMeshDimension()!=3)
6229     throw INTERP_KERNEL::Exception(msg);
6230   int spaceDim=getSpaceDimension();
6231   if(spaceDim!=3)
6232     throw INTERP_KERNEL::Exception(msg);
6233   //
6234   int nbOfCells=getNumberOfCells();
6235   int *conn=_nodal_connec->getPointer();
6236   const int *connI=_nodal_connec_index->getConstPointer();
6237   const double *coo=getCoords()->getConstPointer();
6238   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6239   for(int i=0;i<nbOfCells;i++)
6240     {
6241       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6242       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6243         {
6244           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6245             {
6246               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6247               cells->pushBackSilent(i);
6248             }
6249         }
6250     }
6251   return cells.retn();
6252 }
6253
6254 /*!
6255  * This method is a faster method to correct orientation of all 3D cells in \a this.
6256  * 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.
6257  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
6258  * 
6259  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6260  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6261  */
6262 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6263 {
6264   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6265     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6266   int nbOfCells=getNumberOfCells();
6267   int *conn=_nodal_connec->getPointer();
6268   const int *connI=_nodal_connec_index->getConstPointer();
6269   const double *coordsPtr=_coords->getConstPointer();
6270   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6271   for(int i=0;i<nbOfCells;i++)
6272     {
6273       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6274       switch(type)
6275       {
6276         case INTERP_KERNEL::NORM_TETRA4:
6277           {
6278             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6279               {
6280                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6281                 ret->pushBackSilent(i);
6282               }
6283             break;
6284           }
6285         case INTERP_KERNEL::NORM_PYRA5:
6286           {
6287             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6288               {
6289                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6290                 ret->pushBackSilent(i);
6291               }
6292             break;
6293           }
6294         case INTERP_KERNEL::NORM_PENTA6:
6295         case INTERP_KERNEL::NORM_HEXA8:
6296         case INTERP_KERNEL::NORM_HEXGP12:
6297           {
6298             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6299               {
6300                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6301                 ret->pushBackSilent(i);
6302               }
6303             break;
6304           }
6305         case INTERP_KERNEL::NORM_POLYHED:
6306           {
6307             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6308               {
6309                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6310                 ret->pushBackSilent(i);
6311               }
6312             break;
6313           }
6314         default:
6315           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 !");
6316       }
6317     }
6318   updateTime();
6319   return ret.retn();
6320 }
6321
6322 /*!
6323  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6324  * If it is not the case an exception will be thrown.
6325  * This method is fast because the first cell of \a this is used to compute the plane.
6326  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6327  * \param pos output of size at least 3 used to store a point owned of searched plane.
6328  */
6329 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6330 {
6331   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6332     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6333   const int *conn=_nodal_connec->getConstPointer();
6334   const int *connI=_nodal_connec_index->getConstPointer();
6335   const double *coordsPtr=_coords->getConstPointer();
6336   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6337   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6338 }
6339
6340 /*!
6341  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6342  * cells. Currently cells of the following types are treated:
6343  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6344  * For a cell of other type an exception is thrown.
6345  * Space dimension of a 2D mesh can be either 2 or 3.
6346  * The Edge Ratio of a cell \f$t\f$ is: 
6347  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6348  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6349  *  the smallest edge lengths of \f$t\f$.
6350  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6351  *          cells and one time, lying on \a this mesh. The caller is to delete this
6352  *          field using decrRef() as it is no more needed. 
6353  *  \throw If the coordinates array is not set.
6354  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6355  *  \throw If the connectivity data array has more than one component.
6356  *  \throw If the connectivity data array has a named component.
6357  *  \throw If the connectivity index data array has more than one component.
6358  *  \throw If the connectivity index data array has a named component.
6359  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6360  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6361  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6362  */
6363 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6364 {
6365   checkConsistencyLight();
6366   int spaceDim=getSpaceDimension();
6367   int meshDim=getMeshDimension();
6368   if(spaceDim!=2 && spaceDim!=3)
6369     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6370   if(meshDim!=2 && meshDim!=3)
6371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6372   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6373   ret->setMesh(this);
6374   int nbOfCells=getNumberOfCells();
6375   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6376   arr->alloc(nbOfCells,1);
6377   double *pt=arr->getPointer();
6378   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6379   const int *conn=_nodal_connec->getConstPointer();
6380   const int *connI=_nodal_connec_index->getConstPointer();
6381   const double *coo=_coords->getConstPointer();
6382   double tmp[12];
6383   for(int i=0;i<nbOfCells;i++,pt++)
6384     {
6385       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6386       switch(t)
6387       {
6388         case INTERP_KERNEL::NORM_TRI3:
6389           {
6390             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6391             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6392             break;
6393           }
6394         case INTERP_KERNEL::NORM_QUAD4:
6395           {
6396             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6397             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6398             break;
6399           }
6400         case INTERP_KERNEL::NORM_TETRA4:
6401           {
6402             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6403             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6404             break;
6405           }
6406         default:
6407           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6408       }
6409       conn+=connI[i+1]-connI[i];
6410     }
6411   ret->setName("EdgeRatio");
6412   ret->synchronizeTimeWithSupport();
6413   return ret.retn();
6414 }
6415
6416 /*!
6417  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6418  * cells. Currently cells of the following types are treated:
6419  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6420  * For a cell of other type an exception is thrown.
6421  * Space dimension of a 2D mesh can be either 2 or 3.
6422  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6423  *          cells and one time, lying on \a this mesh. The caller is to delete this
6424  *          field using decrRef() as it is no more needed. 
6425  *  \throw If the coordinates array is not set.
6426  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6427  *  \throw If the connectivity data array has more than one component.
6428  *  \throw If the connectivity data array has a named component.
6429  *  \throw If the connectivity index data array has more than one component.
6430  *  \throw If the connectivity index data array has a named component.
6431  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6432  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6433  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6434  */
6435 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6436 {
6437   checkConsistencyLight();
6438   int spaceDim=getSpaceDimension();
6439   int meshDim=getMeshDimension();
6440   if(spaceDim!=2 && spaceDim!=3)
6441     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6442   if(meshDim!=2 && meshDim!=3)
6443     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6444   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6445   ret->setMesh(this);
6446   int nbOfCells=getNumberOfCells();
6447   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6448   arr->alloc(nbOfCells,1);
6449   double *pt=arr->getPointer();
6450   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6451   const int *conn=_nodal_connec->getConstPointer();
6452   const int *connI=_nodal_connec_index->getConstPointer();
6453   const double *coo=_coords->getConstPointer();
6454   double tmp[12];
6455   for(int i=0;i<nbOfCells;i++,pt++)
6456     {
6457       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6458       switch(t)
6459       {
6460         case INTERP_KERNEL::NORM_TRI3:
6461           {
6462             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6463             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6464             break;
6465           }
6466         case INTERP_KERNEL::NORM_QUAD4:
6467           {
6468             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6469             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6470             break;
6471           }
6472         case INTERP_KERNEL::NORM_TETRA4:
6473           {
6474             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6475             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6476             break;
6477           }
6478         default:
6479           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6480       }
6481       conn+=connI[i+1]-connI[i];
6482     }
6483   ret->setName("AspectRatio");
6484   ret->synchronizeTimeWithSupport();
6485   return ret.retn();
6486 }
6487
6488 /*!
6489  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6490  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
6491  * in 3D space. Currently only cells of the following types are
6492  * treated: INTERP_KERNEL::NORM_QUAD4.
6493  * For a cell of other type an exception is thrown.
6494  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
6495  * Defining
6496  * \f$t=\vec{da}\times\vec{ab}\f$,
6497  * \f$u=\vec{ab}\times\vec{bc}\f$
6498  * \f$v=\vec{bc}\times\vec{cd}\f$
6499  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
6500  *  \f[
6501  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
6502  *  \f]
6503  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6504  *          cells and one time, lying on \a this mesh. The caller is to delete this
6505  *          field using decrRef() as it is no more needed. 
6506  *  \throw If the coordinates array is not set.
6507  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6508  *  \throw If the connectivity data array has more than one component.
6509  *  \throw If the connectivity data array has a named component.
6510  *  \throw If the connectivity index data array has more than one component.
6511  *  \throw If the connectivity index data array has a named component.
6512  *  \throw If \a this->getMeshDimension() != 2.
6513  *  \throw If \a this->getSpaceDimension() != 3.
6514  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6515  */
6516 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6517 {
6518   checkConsistencyLight();
6519   int spaceDim=getSpaceDimension();
6520   int meshDim=getMeshDimension();
6521   if(spaceDim!=3)
6522     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6523   if(meshDim!=2)
6524     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6525   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6526   ret->setMesh(this);
6527   int nbOfCells=getNumberOfCells();
6528   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6529   arr->alloc(nbOfCells,1);
6530   double *pt=arr->getPointer();
6531   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6532   const int *conn=_nodal_connec->getConstPointer();
6533   const int *connI=_nodal_connec_index->getConstPointer();
6534   const double *coo=_coords->getConstPointer();
6535   double tmp[12];
6536   for(int i=0;i<nbOfCells;i++,pt++)
6537     {
6538       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6539       switch(t)
6540       {
6541         case INTERP_KERNEL::NORM_QUAD4:
6542           {
6543             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6544             *pt=INTERP_KERNEL::quadWarp(tmp);
6545             break;
6546           }
6547         default:
6548           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6549       }
6550       conn+=connI[i+1]-connI[i];
6551     }
6552   ret->setName("Warp");
6553   ret->synchronizeTimeWithSupport();
6554   return ret.retn();
6555 }
6556
6557
6558 /*!
6559  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6560  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6561  * treated: INTERP_KERNEL::NORM_QUAD4.
6562  * The skew is computed as follow for a quad with points (a,b,c,d): let
6563  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
6564  * then the skew is computed as:
6565  *  \f[
6566  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
6567  *  \f]
6568  *
6569  * For a cell of other type an exception is thrown.
6570  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6571  *          cells and one time, lying on \a this mesh. The caller is to delete this
6572  *          field using decrRef() as it is no more needed. 
6573  *  \throw If the coordinates array is not set.
6574  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6575  *  \throw If the connectivity data array has more than one component.
6576  *  \throw If the connectivity data array has a named component.
6577  *  \throw If the connectivity index data array has more than one component.
6578  *  \throw If the connectivity index data array has a named component.
6579  *  \throw If \a this->getMeshDimension() != 2.
6580  *  \throw If \a this->getSpaceDimension() != 3.
6581  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6582  */
6583 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6584 {
6585   checkConsistencyLight();
6586   int spaceDim=getSpaceDimension();
6587   int meshDim=getMeshDimension();
6588   if(spaceDim!=3)
6589     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6590   if(meshDim!=2)
6591     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6592   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6593   ret->setMesh(this);
6594   int nbOfCells=getNumberOfCells();
6595   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6596   arr->alloc(nbOfCells,1);
6597   double *pt=arr->getPointer();
6598   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6599   const int *conn=_nodal_connec->getConstPointer();
6600   const int *connI=_nodal_connec_index->getConstPointer();
6601   const double *coo=_coords->getConstPointer();
6602   double tmp[12];
6603   for(int i=0;i<nbOfCells;i++,pt++)
6604     {
6605       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6606       switch(t)
6607       {
6608         case INTERP_KERNEL::NORM_QUAD4:
6609           {
6610             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6611             *pt=INTERP_KERNEL::quadSkew(tmp);
6612             break;
6613           }
6614         default:
6615           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6616       }
6617       conn+=connI[i+1]-connI[i];
6618     }
6619   ret->setName("Skew");
6620   ret->synchronizeTimeWithSupport();
6621   return ret.retn();
6622 }
6623
6624 /*!
6625  * Returns the cell field giving for each cell in \a this its diameter. Diameter means the max length of all possible SEG2 in the cell.
6626  *
6627  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6628  *
6629  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6630  */
6631 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6632 {
6633   checkConsistencyLight();
6634   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6635   ret->setMesh(this);
6636   std::set<INTERP_KERNEL::NormalizedCellType> types;
6637   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6638   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6639   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6640   arr->alloc(nbCells,1);
6641   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6642     {
6643       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6644       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
6645       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6646     }
6647   ret->setArray(arr);
6648   ret->setName("Diameter");
6649   return ret.retn();
6650 }
6651
6652 /*!
6653  * This method aggregate the bbox of each cell and put it into bbox parameter.
6654  * 
6655  * \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)
6656  *                         For all other cases this input parameter is ignored.
6657  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6658  * 
6659  * \throw If \a this is not fully set (coordinates and connectivity).
6660  * \throw If a cell in \a this has no valid nodeId.
6661  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6662  */
6663 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6664 {
6665   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6666   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.
6667     return getBoundingBoxForBBTreeFast();
6668   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6669     {
6670       bool presenceOfQuadratic(false);
6671       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6672         {
6673           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6674           if(cm.isQuadratic())
6675             presenceOfQuadratic=true;
6676         }
6677       if(!presenceOfQuadratic)
6678         return getBoundingBoxForBBTreeFast();
6679       if(mDim==2 && sDim==2)
6680         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6681       else
6682         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6683     }
6684   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) !");
6685 }
6686
6687 /*!
6688  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6689  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6690  * 
6691  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6692  * 
6693  * \throw If \a this is not fully set (coordinates and connectivity).
6694  * \throw If a cell in \a this has no valid nodeId.
6695  */
6696 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6697 {
6698   checkFullyDefined();
6699   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6700   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6701   double *bbox(ret->getPointer());
6702   for(int i=0;i<nbOfCells*spaceDim;i++)
6703     {
6704       bbox[2*i]=std::numeric_limits<double>::max();
6705       bbox[2*i+1]=-std::numeric_limits<double>::max();
6706     }
6707   const double *coordsPtr(_coords->getConstPointer());
6708   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6709   for(int i=0;i<nbOfCells;i++)
6710     {
6711       int offset=connI[i]+1;
6712       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6713       for(int j=0;j<nbOfNodesForCell;j++)
6714         {
6715           int nodeId=conn[offset+j];
6716           if(nodeId>=0 && nodeId<nbOfNodes)
6717             {
6718               for(int k=0;k<spaceDim;k++)
6719                 {
6720                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6721                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6722                 }
6723               kk++;
6724             }
6725         }
6726       if(kk==0)
6727         {
6728           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6729           throw INTERP_KERNEL::Exception(oss.str().c_str());
6730         }
6731     }
6732   return ret.retn();
6733 }
6734
6735 /*!
6736  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6737  * useful for 2D meshes having quadratic cells
6738  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6739  * the two extremities of the arc of circle).
6740  * 
6741  * \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)
6742  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6743  * \throw If \a this is not fully defined.
6744  * \throw If \a this is not a mesh with meshDimension equal to 2.
6745  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6746  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6747  */
6748 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6749 {
6750   checkFullyDefined();
6751   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6752   if(spaceDim!=2 || mDim!=2)
6753     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!");
6754   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6755   double *bbox(ret->getPointer());
6756   const double *coords(_coords->getConstPointer());
6757   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6758   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6759     {
6760       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6761       int sz(connI[1]-connI[0]-1);
6762       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6763       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6764       INTERP_KERNEL::QuadraticPolygon *pol(0);
6765       for(int j=0;j<sz;j++)
6766         {
6767           int nodeId(conn[*connI+1+j]);
6768           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6769         }
6770       if(!cm.isQuadratic())
6771         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6772       else
6773         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6774       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6775       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6776     }
6777   return ret.retn();
6778 }
6779
6780 /*!
6781  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6782  * useful for 2D meshes having quadratic cells
6783  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6784  * the two extremities of the arc of circle).
6785  * 
6786  * \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)
6787  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6788  * \throw If \a this is not fully defined.
6789  * \throw If \a this is not a mesh with meshDimension equal to 1.
6790  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6791  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6792  */
6793 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6794 {
6795   checkFullyDefined();
6796   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6797   if(spaceDim!=2 || mDim!=1)
6798     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!");
6799   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6800   double *bbox(ret->getPointer());
6801   const double *coords(_coords->getConstPointer());
6802   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6803   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6804     {
6805       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6806       int sz(connI[1]-connI[0]-1);
6807       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6808       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6809       INTERP_KERNEL::Edge *edge(0);
6810       for(int j=0;j<sz;j++)
6811         {
6812           int nodeId(conn[*connI+1+j]);
6813           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6814         }
6815       if(!cm.isQuadratic())
6816         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6817       else
6818         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6819       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6820       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6821     }
6822   return ret.retn();
6823 }
6824
6825 /// @cond INTERNAL
6826
6827 namespace MEDCouplingImpl
6828 {
6829   class ConnReader
6830   {
6831   public:
6832     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6833     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6834   private:
6835     const int *_conn;
6836     int _val;
6837   };
6838
6839   class ConnReader2
6840   {
6841   public:
6842     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6843     bool operator() (const int& pos) { return _conn[pos]==_val; }
6844   private:
6845     const int *_conn;
6846     int _val;
6847   };
6848 }
6849
6850 /// @endcond
6851
6852 /*!
6853  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6854  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6855  * \a this is composed in cell types.
6856  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6857  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6858  * This parameter is kept only for compatibility with other methode listed above.
6859  */
6860 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6861 {
6862   checkConnectivityFullyDefined();
6863   const int *conn=_nodal_connec->getConstPointer();
6864   const int *connI=_nodal_connec_index->getConstPointer();
6865   const int *work=connI;
6866   int nbOfCells=getNumberOfCells();
6867   std::size_t n=getAllGeoTypes().size();
6868   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6869   std::set<INTERP_KERNEL::NormalizedCellType> types;
6870   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6871     {
6872       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6873       if(types.find(typ)!=types.end())
6874         {
6875           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6876           oss << " is not contiguous !";
6877           throw INTERP_KERNEL::Exception(oss.str().c_str());
6878         }
6879       types.insert(typ);
6880       ret[3*i]=typ;
6881       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
6882       ret[3*i+1]=(int)std::distance(work,work2);
6883       work=work2;
6884     }
6885   return ret;
6886 }
6887
6888 /*!
6889  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6890  * only for types cell, type node is not managed.
6891  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6892  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6893  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6894  * If 2 or more same geometric type is in \a code and exception is thrown too.
6895  *
6896  * This method firstly checks
6897  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6898  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6899  * an exception is thrown too.
6900  * 
6901  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6902  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6903  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6904  */
6905 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6906 {
6907   if(code.empty())
6908     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6909   std::size_t sz=code.size();
6910   std::size_t n=sz/3;
6911   if(sz%3!=0)
6912     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6913   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6914   int nb=0;
6915   bool isNoPflUsed=true;
6916   for(std::size_t i=0;i<n;i++)
6917     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6918       {
6919         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6920         nb+=code[3*i+1];
6921         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6922           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6923         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6924       }
6925   if(types.size()!=n)
6926     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6927   if(isNoPflUsed)
6928     {
6929       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6930         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6931       if(types.size()==_types.size())
6932         return 0;
6933     }
6934   MCAuto<DataArrayInt> ret=DataArrayInt::New();
6935   ret->alloc(nb,1);
6936   int *retPtr=ret->getPointer();
6937   const int *connI=_nodal_connec_index->getConstPointer();
6938   const int *conn=_nodal_connec->getConstPointer();
6939   int nbOfCells=getNumberOfCells();
6940   const int *i=connI;
6941   int kk=0;
6942   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6943     {
6944       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
6945       int offset=(int)std::distance(connI,i);
6946       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
6947       int nbOfCellsOfCurType=(int)std::distance(i,j);
6948       if(code[3*kk+2]==-1)
6949         for(int k=0;k<nbOfCellsOfCurType;k++)
6950           *retPtr++=k+offset;
6951       else
6952         {
6953           int idInIdsPerType=code[3*kk+2];
6954           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6955             {
6956               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6957               if(zePfl)
6958                 {
6959                   zePfl->checkAllocated();
6960                   if(zePfl->getNumberOfComponents()==1)
6961                     {
6962                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6963                         {
6964                           if(*k>=0 && *k<nbOfCellsOfCurType)
6965                             *retPtr=(*k)+offset;
6966                           else
6967                             {
6968                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6969                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6970                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6971                             }
6972                         }
6973                     }
6974                   else
6975                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6976                 }
6977               else
6978                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6979             }
6980           else
6981             {
6982               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6983               oss << " should be in [0," << idsPerType.size() << ") !";
6984               throw INTERP_KERNEL::Exception(oss.str().c_str());
6985             }
6986         }
6987       i=j;
6988     }
6989   return ret.retn();
6990 }
6991
6992 /*!
6993  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6994  * 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.
6995  * 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.
6996  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6997  * 
6998  * \param [in] profile
6999  * \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.
7000  * \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,
7001  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
7002  * \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.
7003  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
7004  * \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
7005  */
7006 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
7007 {
7008   if(!profile)
7009     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
7010   if(profile->getNumberOfComponents()!=1)
7011     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
7012   checkConnectivityFullyDefined();
7013   const int *conn=_nodal_connec->getConstPointer();
7014   const int *connI=_nodal_connec_index->getConstPointer();
7015   int nbOfCells=getNumberOfCells();
7016   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7017   std::vector<int> typeRangeVals(1);
7018   for(const int *i=connI;i!=connI+nbOfCells;)
7019     {
7020       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7021       if(std::find(types.begin(),types.end(),curType)!=types.end())
7022         {
7023           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
7024         }
7025       types.push_back(curType);
7026       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7027       typeRangeVals.push_back((int)std::distance(connI,i));
7028     }
7029   //
7030   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
7031   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
7032   MCAuto<DataArrayInt> tmp0=castArr;
7033   MCAuto<DataArrayInt> tmp1=rankInsideCast;
7034   MCAuto<DataArrayInt> tmp2=castsPresent;
7035   //
7036   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7037   code.resize(3*nbOfCastsFinal);
7038   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
7039   std::vector< MCAuto<DataArrayInt> > idsPerType2;
7040   for(int i=0;i<nbOfCastsFinal;i++)
7041     {
7042       int castId=castsPresent->getIJ(i,0);
7043       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
7044       idsInPflPerType2.push_back(tmp3);
7045       code[3*i]=(int)types[castId];
7046       code[3*i+1]=tmp3->getNumberOfTuples();
7047       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7048       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
7049         {
7050           tmp4->copyStringInfoFrom(*profile);
7051           idsPerType2.push_back(tmp4);
7052           code[3*i+2]=(int)idsPerType2.size()-1;
7053         }
7054       else
7055         {
7056           code[3*i+2]=-1;
7057         }
7058     }
7059   std::size_t sz2=idsInPflPerType2.size();
7060   idsInPflPerType.resize(sz2);
7061   for(std::size_t i=0;i<sz2;i++)
7062     {
7063       DataArrayInt *locDa=idsInPflPerType2[i];
7064       locDa->incrRef();
7065       idsInPflPerType[i]=locDa;
7066     }
7067   std::size_t sz=idsPerType2.size();
7068   idsPerType.resize(sz);
7069   for(std::size_t i=0;i<sz;i++)
7070     {
7071       DataArrayInt *locDa=idsPerType2[i];
7072       locDa->incrRef();
7073       idsPerType[i]=locDa;
7074     }
7075 }
7076
7077 /*!
7078  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7079  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7080  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7081  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as MEDCoupling::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.
7082  */
7083 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7084 {
7085   checkFullyDefined();
7086   nM1LevMesh->checkFullyDefined();
7087   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7088     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7089   if(_coords!=nM1LevMesh->getCoords())
7090     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7091   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
7092   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
7093   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7094   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7095   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7096   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7097   tmp->setConnectivity(tmp0,tmp1);
7098   tmp->renumberCells(ret0->getConstPointer(),false);
7099   revDesc=tmp->getNodalConnectivity();
7100   revDescIndx=tmp->getNodalConnectivityIndex();
7101   DataArrayInt *ret=0;
7102   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7103     {
7104       int tmp2;
7105       ret->getMaxValue(tmp2);
7106       ret->decrRef();
7107       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7108       throw INTERP_KERNEL::Exception(oss.str().c_str());
7109     }
7110   nM1LevMeshIds=ret;
7111   //
7112   revDesc->incrRef();
7113   revDescIndx->incrRef();
7114   ret1->incrRef();
7115   ret0->incrRef();
7116   meshnM1Old2New=ret0;
7117   return ret1;
7118 }
7119
7120 /*!
7121  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7122  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7123  * in "Old to New" mode.
7124  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7125  *          this array using decrRef() as it is no more needed.
7126  *  \throw If the nodal connectivity of cells is not defined.
7127  */
7128 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7129 {
7130   checkConnectivityFullyDefined();
7131   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7132   renumberCells(ret->getConstPointer(),false);
7133   return ret.retn();
7134 }
7135
7136 /*!
7137  * This methods checks that cells are sorted by their types.
7138  * This method makes asumption (no check) that connectivity is correctly set before calling.
7139  */
7140 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7141 {
7142   checkFullyDefined();
7143   const int *conn=_nodal_connec->getConstPointer();
7144   const int *connI=_nodal_connec_index->getConstPointer();
7145   int nbOfCells=getNumberOfCells();
7146   std::set<INTERP_KERNEL::NormalizedCellType> types;
7147   for(const int *i=connI;i!=connI+nbOfCells;)
7148     {
7149       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7150       if(types.find(curType)!=types.end())
7151         return false;
7152       types.insert(curType);
7153       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7154     }
7155   return true;
7156 }
7157
7158 /*!
7159  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7160  * The geometric type order is specified by MED file.
7161  * 
7162  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7163  */
7164 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7165 {
7166   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7167 }
7168
7169 /*!
7170  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7171  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7172  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7173  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7174  */
7175 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7176 {
7177   checkFullyDefined();
7178   const int *conn=_nodal_connec->getConstPointer();
7179   const int *connI=_nodal_connec_index->getConstPointer();
7180   int nbOfCells=getNumberOfCells();
7181   if(nbOfCells==0)
7182     return true;
7183   int lastPos=-1;
7184   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7185   for(const int *i=connI;i!=connI+nbOfCells;)
7186     {
7187       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7188       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7189       if(isTypeExists!=orderEnd)
7190         {
7191           int pos=(int)std::distance(orderBg,isTypeExists);
7192           if(pos<=lastPos)
7193             return false;
7194           lastPos=pos;
7195           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7196         }
7197       else
7198         {
7199           if(sg.find(curType)==sg.end())
7200             {
7201               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7202               sg.insert(curType);
7203             }
7204           else
7205             return false;
7206         }
7207     }
7208   return true;
7209 }
7210
7211 /*!
7212  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7213  * 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
7214  * 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'.
7215  */
7216 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7217 {
7218   checkConnectivityFullyDefined();
7219   int nbOfCells=getNumberOfCells();
7220   const int *conn=_nodal_connec->getConstPointer();
7221   const int *connI=_nodal_connec_index->getConstPointer();
7222   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
7223   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
7224   tmpa->alloc(nbOfCells,1);
7225   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7226   tmpb->fillWithZero();
7227   int *tmp=tmpa->getPointer();
7228   int *tmp2=tmpb->getPointer();
7229   for(const int *i=connI;i!=connI+nbOfCells;i++)
7230     {
7231       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7232       if(where!=orderEnd)
7233         {
7234           int pos=(int)std::distance(orderBg,where);
7235           tmp2[pos]++;
7236           tmp[std::distance(connI,i)]=pos;
7237         }
7238       else
7239         {
7240           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7241           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7242           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7243           throw INTERP_KERNEL::Exception(oss.str().c_str());
7244         }
7245     }
7246   nbPerType=tmpb.retn();
7247   return tmpa.retn();
7248 }
7249
7250 /*!
7251  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7252  *
7253  * \return a new object containing the old to new correspondance.
7254  *
7255  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7256  */
7257 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7258 {
7259   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7260 }
7261
7262 /*!
7263  * 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.
7264  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7265  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7266  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7267  */
7268 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7269 {
7270   DataArrayInt *nbPerType=0;
7271   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7272   nbPerType->decrRef();
7273   return tmpa->buildPermArrPerLevel();
7274 }
7275
7276 /*!
7277  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7278  * The number of cells remains unchanged after the call of this method.
7279  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7280  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7281  *
7282  * \return the array giving the correspondance old to new.
7283  */
7284 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7285 {
7286   checkFullyDefined();
7287   computeTypes();
7288   const int *conn=_nodal_connec->getConstPointer();
7289   const int *connI=_nodal_connec_index->getConstPointer();
7290   int nbOfCells=getNumberOfCells();
7291   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7292   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7293     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7294       {
7295         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7296         types.push_back(curType);
7297         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7298       }
7299   DataArrayInt *ret=DataArrayInt::New();
7300   ret->alloc(nbOfCells,1);
7301   int *retPtr=ret->getPointer();
7302   std::fill(retPtr,retPtr+nbOfCells,-1);
7303   int newCellId=0;
7304   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7305     {
7306       for(const int *i=connI;i!=connI+nbOfCells;i++)
7307         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7308           retPtr[std::distance(connI,i)]=newCellId++;
7309     }
7310   renumberCells(retPtr,false);
7311   return ret;
7312 }
7313
7314 /*!
7315  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7316  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7317  * This method makes asumption that connectivity is correctly set before calling.
7318  */
7319 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7320 {
7321   checkConnectivityFullyDefined();
7322   const int *conn=_nodal_connec->getConstPointer();
7323   const int *connI=_nodal_connec_index->getConstPointer();
7324   int nbOfCells=getNumberOfCells();
7325   std::vector<MEDCouplingUMesh *> ret;
7326   for(const int *i=connI;i!=connI+nbOfCells;)
7327     {
7328       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7329       int beginCellId=(int)std::distance(connI,i);
7330       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7331       int endCellId=(int)std::distance(connI,i);
7332       int sz=endCellId-beginCellId;
7333       int *cells=new int[sz];
7334       for(int j=0;j<sz;j++)
7335         cells[j]=beginCellId+j;
7336       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7337       delete [] cells;
7338       ret.push_back(m);
7339     }
7340   return ret;
7341 }
7342
7343 /*!
7344  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7345  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7346  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7347  *
7348  * \return a newly allocated instance, that the caller must manage.
7349  * \throw If \a this contains more than one geometric type.
7350  * \throw If the nodal connectivity of \a this is not fully defined.
7351  * \throw If the internal data is not coherent.
7352  */
7353 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7354 {
7355   checkConnectivityFullyDefined();
7356   if(_types.size()!=1)
7357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7358   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7359   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7360   ret->setCoords(getCoords());
7361   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7362   if(retC)
7363     {
7364       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7365       retC->setNodalConnectivity(c);
7366     }
7367   else
7368     {
7369       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7370       if(!retD)
7371         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7372       DataArrayInt *c=0,*ci=0;
7373       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7374       MCAuto<DataArrayInt> cs(c),cis(ci);
7375       retD->setNodalConnectivity(cs,cis);
7376     }
7377   return ret.retn();
7378 }
7379
7380 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7381 {
7382   checkConnectivityFullyDefined();
7383   if(_types.size()!=1)
7384     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7385   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7386   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7387   if(cm.isDynamic())
7388     {
7389       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7390       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7391       throw INTERP_KERNEL::Exception(oss.str().c_str());
7392     }
7393   int nbCells=getNumberOfCells();
7394   int typi=(int)typ;
7395   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7396   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7397   int *outPtr=connOut->getPointer();
7398   const int *conn=_nodal_connec->begin();
7399   const int *connI=_nodal_connec_index->begin();
7400   nbNodesPerCell++;
7401   for(int i=0;i<nbCells;i++,connI++)
7402     {
7403       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7404         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7405       else
7406         {
7407           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 << ") !";
7408           throw INTERP_KERNEL::Exception(oss.str().c_str());
7409         }
7410     }
7411   return connOut.retn();
7412 }
7413
7414 /*!
7415  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7416  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7417  * \param nodalConn
7418  * \param nodalConnI
7419  */
7420 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7421 {
7422   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
7423   checkConnectivityFullyDefined();
7424   if(_types.size()!=1)
7425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7426   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7427   if(lgth<nbCells)
7428     throw INTERP_KERNEL::Exception(msg0);
7429   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7430   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7431   int *cp(c->getPointer()),*cip(ci->getPointer());
7432   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7433   cip[0]=0;
7434   for(int i=0;i<nbCells;i++,cip++,incip++)
7435     {
7436       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7437       int delta(stop-strt);
7438       if(delta>=1)
7439         {
7440           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7441             cp=std::copy(incp+strt,incp+stop,cp);
7442           else
7443             throw INTERP_KERNEL::Exception(msg0);
7444         }
7445       else
7446         throw INTERP_KERNEL::Exception(msg0);
7447       cip[1]=cip[0]+delta;
7448     }
7449   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7450 }
7451
7452 /*!
7453  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7454  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7455  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7456  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7457  * are not used here to avoid the build of big permutation array.
7458  *
7459  * \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
7460  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7461  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7462  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7463  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7464  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7465  * \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
7466  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7467  */
7468 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7469                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7470                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7471 {
7472   std::vector<const MEDCouplingUMesh *> ms2;
7473   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7474     if(*it)
7475       {
7476         (*it)->checkConnectivityFullyDefined();
7477         ms2.push_back(*it);
7478       }
7479   if(ms2.empty())
7480     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7481   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7482   int meshDim=ms2[0]->getMeshDimension();
7483   std::vector<const MEDCouplingUMesh *> m1ssm;
7484   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
7485   //
7486   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7487   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
7488   int fake=0,rk=0;
7489   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7490   ret1->alloc(0,1); ret2->alloc(0,1);
7491   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7492     {
7493       if(meshDim!=(*it)->getMeshDimension())
7494         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7495       if(refCoo!=(*it)->getCoords())
7496         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7497       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7498       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7499       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
7500       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7501         {
7502           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7503           m1ssmSingleAuto.push_back(singleCell);
7504           m1ssmSingle.push_back(singleCell);
7505           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7506         }
7507     }
7508   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7509   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7510   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7511   for(std::size_t i=0;i<m1ssm.size();i++)
7512     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7513   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7514   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7515   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7516   return ret0.retn();
7517 }
7518
7519 /*!
7520  * This method returns a newly created DataArrayInt instance.
7521  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7522  */
7523 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7524 {
7525   checkFullyDefined();
7526   const int *conn=_nodal_connec->getConstPointer();
7527   const int *connIndex=_nodal_connec_index->getConstPointer();
7528   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7529   for(const int *w=begin;w!=end;w++)
7530     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7531       ret->pushBackSilent(*w);
7532   return ret.retn();
7533 }
7534
7535 /*!
7536  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7537  * are in [0:getNumberOfCells())
7538  */
7539 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7540 {
7541   checkFullyDefined();
7542   const int *conn=_nodal_connec->getConstPointer();
7543   const int *connI=_nodal_connec_index->getConstPointer();
7544   int nbOfCells=getNumberOfCells();
7545   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7546   int *tmp=new int[nbOfCells];
7547   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7548     {
7549       int j=0;
7550       for(const int *i=connI;i!=connI+nbOfCells;i++)
7551         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7552           tmp[std::distance(connI,i)]=j++;
7553     }
7554   DataArrayInt *ret=DataArrayInt::New();
7555   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7556   ret->copyStringInfoFrom(*da);
7557   int *retPtr=ret->getPointer();
7558   const int *daPtr=da->getConstPointer();
7559   int nbOfElems=da->getNbOfElems();
7560   for(int k=0;k<nbOfElems;k++)
7561     retPtr[k]=tmp[daPtr[k]];
7562   delete [] tmp;
7563   return ret;
7564 }
7565
7566 /*!
7567  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7568  * This method \b works \b for mesh sorted by type.
7569  * cells whose ids is in 'idsPerGeoType' array.
7570  * This method conserves coords and name of mesh.
7571  */
7572 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7573 {
7574   std::vector<int> code=getDistributionOfTypes();
7575   std::size_t nOfTypesInThis=code.size()/3;
7576   int sz=0,szOfType=0;
7577   for(std::size_t i=0;i<nOfTypesInThis;i++)
7578     {
7579       if(code[3*i]!=type)
7580         sz+=code[3*i+1];
7581       else
7582         szOfType=code[3*i+1];
7583     }
7584   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7585     if(*work<0 || *work>=szOfType)
7586       {
7587         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7588         oss << ". It should be in [0," << szOfType << ") !";
7589         throw INTERP_KERNEL::Exception(oss.str().c_str());
7590       }
7591   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7592   int *idsPtr=idsTokeep->getPointer();
7593   int offset=0;
7594   for(std::size_t i=0;i<nOfTypesInThis;i++)
7595     {
7596       if(code[3*i]!=type)
7597         for(int j=0;j<code[3*i+1];j++)
7598           *idsPtr++=offset+j;
7599       else
7600         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7601       offset+=code[3*i+1];
7602     }
7603   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7604   ret->copyTinyInfoFrom(this);
7605   return ret.retn();
7606 }
7607
7608 /*!
7609  * This method returns a vector of size 'this->getNumberOfCells()'.
7610  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7611  */
7612 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7613 {
7614   int ncell=getNumberOfCells();
7615   std::vector<bool> ret(ncell);
7616   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7617   const int *c=getNodalConnectivity()->getConstPointer();
7618   for(int i=0;i<ncell;i++)
7619     {
7620       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7621       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7622       ret[i]=cm.isQuadratic();
7623     }
7624   return ret;
7625 }
7626
7627 /*!
7628  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7629  */
7630 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7631 {
7632   if(other->getType()!=UNSTRUCTURED)
7633     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7634   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7635   return MergeUMeshes(this,otherC);
7636 }
7637
7638 /*!
7639  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7640  * computed by averaging coordinates of cell nodes, so this method is not a right
7641  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7642  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7643  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7644  *          components. The caller is to delete this array using decrRef() as it is
7645  *          no more needed.
7646  *  \throw If the coordinates array is not set.
7647  *  \throw If the nodal connectivity of cells is not defined.
7648  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7649  */
7650 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
7651 {
7652   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7653   int spaceDim=getSpaceDimension();
7654   int nbOfCells=getNumberOfCells();
7655   ret->alloc(nbOfCells,spaceDim);
7656   ret->copyStringInfoFrom(*getCoords());
7657   double *ptToFill=ret->getPointer();
7658   const int *nodal=_nodal_connec->getConstPointer();
7659   const int *nodalI=_nodal_connec_index->getConstPointer();
7660   const double *coor=_coords->getConstPointer();
7661   for(int i=0;i<nbOfCells;i++)
7662     {
7663       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7664       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7665       ptToFill+=spaceDim;
7666     }
7667   return ret.retn();
7668 }
7669
7670 /*!
7671  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7672  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
7673  * 
7674  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7675  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7676  * 
7677  * \sa MEDCouplingUMesh::computeCellCenterOfMass
7678  * \throw If \a this is not fully defined (coordinates and connectivity)
7679  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7680  */
7681 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7682 {
7683   checkFullyDefined();
7684   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7685   int spaceDim=getSpaceDimension();
7686   int nbOfCells=getNumberOfCells();
7687   int nbOfNodes=getNumberOfNodes();
7688   ret->alloc(nbOfCells,spaceDim);
7689   double *ptToFill=ret->getPointer();
7690   const int *nodal=_nodal_connec->getConstPointer();
7691   const int *nodalI=_nodal_connec_index->getConstPointer();
7692   const double *coor=_coords->getConstPointer();
7693   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7694     {
7695       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7696       std::fill(ptToFill,ptToFill+spaceDim,0.);
7697       if(type!=INTERP_KERNEL::NORM_POLYHED)
7698         {
7699           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7700             {
7701               if(*conn>=0 && *conn<nbOfNodes)
7702                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7703               else
7704                 {
7705                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7706                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7707                 }
7708             }
7709           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7710           if(nbOfNodesInCell>0)
7711             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7712           else
7713             {
7714               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7715               throw INTERP_KERNEL::Exception(oss.str().c_str());
7716             }
7717         }
7718       else
7719         {
7720           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7721           s.erase(-1);
7722           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7723             {
7724               if(*it>=0 && *it<nbOfNodes)
7725                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7726               else
7727                 {
7728                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7729                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7730                 }
7731             }
7732           if(!s.empty())
7733             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7734           else
7735             {
7736               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7737               throw INTERP_KERNEL::Exception(oss.str().c_str());
7738             }
7739         }
7740     }
7741   return ret.retn();
7742 }
7743
7744 /*!
7745  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7746  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7747  * are specified via an array of cell ids. 
7748  *  \warning Validity of the specified cell ids is not checked! 
7749  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7750  *  \param [in] begin - an array of cell ids of interest.
7751  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7752  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7753  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7754  *          caller is to delete this array using decrRef() as it is no more needed. 
7755  *  \throw If the coordinates array is not set.
7756  *  \throw If the nodal connectivity of cells is not defined.
7757  *
7758  *  \if ENABLE_EXAMPLES
7759  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7760  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7761  *  \endif
7762  */
7763 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7764 {
7765   DataArrayDouble *ret=DataArrayDouble::New();
7766   int spaceDim=getSpaceDimension();
7767   int nbOfTuple=(int)std::distance(begin,end);
7768   ret->alloc(nbOfTuple,spaceDim);
7769   double *ptToFill=ret->getPointer();
7770   double *tmp=new double[spaceDim];
7771   const int *nodal=_nodal_connec->getConstPointer();
7772   const int *nodalI=_nodal_connec_index->getConstPointer();
7773   const double *coor=_coords->getConstPointer();
7774   for(const int *w=begin;w!=end;w++)
7775     {
7776       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7777       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7778       ptToFill+=spaceDim;
7779     }
7780   delete [] tmp;
7781   return ret;
7782 }
7783
7784 /*!
7785  * 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".
7786  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7787  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7788  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7789  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7790  * 
7791  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7792  * \throw If spaceDim!=3 or meshDim!=2.
7793  * \throw If connectivity of \a this is invalid.
7794  * \throw If connectivity of a cell in \a this points to an invalid node.
7795  */
7796 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7797 {
7798   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
7799   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7800   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7801     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7802   ret->alloc(nbOfCells,4);
7803   double *retPtr(ret->getPointer());
7804   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7805   const double *coor(_coords->begin());
7806   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7807     {
7808       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7809       if(nodalI[1]-nodalI[0]>=3)
7810         {
7811           for(int j=0;j<3;j++)
7812             {
7813               int nodeId(nodal[nodalI[0]+1+j]);
7814               if(nodeId>=0 && nodeId<nbOfNodes)
7815                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7816               else
7817                 {
7818                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7819                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7820                 }
7821             }
7822         }
7823       else
7824         {
7825           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7826           throw INTERP_KERNEL::Exception(oss.str().c_str());
7827         }
7828       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7829       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7830     }
7831   return ret.retn();
7832 }
7833
7834 /*!
7835  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7836  * 
7837  */
7838 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7839 {
7840   if(!da)
7841     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7842   da->checkAllocated();
7843   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7844   ret->setCoords(da);
7845   int nbOfTuples=da->getNumberOfTuples();
7846   MCAuto<DataArrayInt> c=DataArrayInt::New();
7847   MCAuto<DataArrayInt> cI=DataArrayInt::New();
7848   c->alloc(2*nbOfTuples,1);
7849   cI->alloc(nbOfTuples+1,1);
7850   int *cp=c->getPointer();
7851   int *cip=cI->getPointer();
7852   *cip++=0;
7853   for(int i=0;i<nbOfTuples;i++)
7854     {
7855       *cp++=INTERP_KERNEL::NORM_POINT1;
7856       *cp++=i;
7857       *cip++=2*(i+1);
7858     }
7859   ret->setConnectivity(c,cI,true);
7860   return ret.retn();
7861 }
7862 /*!
7863  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7864  * Cells and nodes of
7865  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7866  *  \param [in] mesh1 - the first mesh.
7867  *  \param [in] mesh2 - the second mesh.
7868  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7869  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7870  *          is no more needed.
7871  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7872  *  \throw If the coordinates array is not set in none of the meshes.
7873  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7874  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7875  */
7876 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7877 {
7878   std::vector<const MEDCouplingUMesh *> tmp(2);
7879   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7880   return MergeUMeshes(tmp);
7881 }
7882
7883 /*!
7884  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7885  * Cells and nodes of
7886  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7887  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7888  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7889  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7890  *          is no more needed.
7891  *  \throw If \a a.size() == 0.
7892  *  \throw If \a a[ *i* ] == NULL.
7893  *  \throw If the coordinates array is not set in none of the meshes.
7894  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7895  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7896  */
7897 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7898 {
7899   std::size_t sz=a.size();
7900   if(sz==0)
7901     return MergeUMeshesLL(a);
7902   for(std::size_t ii=0;ii<sz;ii++)
7903     if(!a[ii])
7904       {
7905         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7906         throw INTERP_KERNEL::Exception(oss.str().c_str());
7907       }
7908   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
7909   std::vector< const MEDCouplingUMesh * > aa(sz);
7910   int spaceDim=-3;
7911   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7912     {
7913       const MEDCouplingUMesh *cur=a[i];
7914       const DataArrayDouble *coo=cur->getCoords();
7915       if(coo)
7916         spaceDim=coo->getNumberOfComponents();
7917     }
7918   if(spaceDim==-3)
7919     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7920   for(std::size_t i=0;i<sz;i++)
7921     {
7922       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7923       aa[i]=bb[i];
7924     }
7925   return MergeUMeshesLL(aa);
7926 }
7927
7928 /// @cond INTERNAL
7929
7930 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7931 {
7932   if(a.empty())
7933     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7934   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7935   int meshDim=(*it)->getMeshDimension();
7936   int nbOfCells=(*it)->getNumberOfCells();
7937   int meshLgth=(*it++)->getNodalConnectivityArrayLen();
7938   for(;it!=a.end();it++)
7939     {
7940       if(meshDim!=(*it)->getMeshDimension())
7941         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7942       nbOfCells+=(*it)->getNumberOfCells();
7943       meshLgth+=(*it)->getNodalConnectivityArrayLen();
7944     }
7945   std::vector<const MEDCouplingPointSet *> aps(a.size());
7946   std::copy(a.begin(),a.end(),aps.begin());
7947   MCAuto<DataArrayDouble> pts=MergeNodesArray(aps);
7948   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7949   ret->setCoords(pts);
7950   MCAuto<DataArrayInt> c=DataArrayInt::New();
7951   c->alloc(meshLgth,1);
7952   int *cPtr=c->getPointer();
7953   MCAuto<DataArrayInt> cI=DataArrayInt::New();
7954   cI->alloc(nbOfCells+1,1);
7955   int *cIPtr=cI->getPointer();
7956   *cIPtr++=0;
7957   int offset=0;
7958   int offset2=0;
7959   for(it=a.begin();it!=a.end();it++)
7960     {
7961       int curNbOfCell=(*it)->getNumberOfCells();
7962       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7963       const int *curC=(*it)->_nodal_connec->getConstPointer();
7964       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7965       for(int j=0;j<curNbOfCell;j++)
7966         {
7967           const int *src=curC+curCI[j];
7968           *cPtr++=*src++;
7969           for(;src!=curC+curCI[j+1];src++,cPtr++)
7970             {
7971               if(*src!=-1)
7972                 *cPtr=*src+offset2;
7973               else
7974                 *cPtr=-1;
7975             }
7976         }
7977       offset+=curCI[curNbOfCell];
7978       offset2+=(*it)->getNumberOfNodes();
7979     }
7980   //
7981   ret->setConnectivity(c,cI,true);
7982   return ret.retn();
7983 }
7984
7985 /// @endcond
7986
7987 /*!
7988  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7989  * dimension and sharing the node coordinates array.
7990  * All cells of the first mesh precede all cells of the second mesh
7991  * within the result mesh. 
7992  *  \param [in] mesh1 - the first mesh.
7993  *  \param [in] mesh2 - the second mesh.
7994  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7995  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7996  *          is no more needed.
7997  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7998  *  \throw If the meshes do not share the node coordinates array.
7999  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
8000  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
8001  */
8002 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
8003 {
8004   std::vector<const MEDCouplingUMesh *> tmp(2);
8005   tmp[0]=mesh1; tmp[1]=mesh2;
8006   return MergeUMeshesOnSameCoords(tmp);
8007 }
8008
8009 /*!
8010  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8011  * dimension and sharing the node coordinates array.
8012  * All cells of the *i*-th mesh precede all cells of the
8013  * (*i*+1)-th mesh within the result mesh.
8014  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8015  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8016  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8017  *          is no more needed.
8018  *  \throw If \a a.size() == 0.
8019  *  \throw If \a a[ *i* ] == NULL.
8020  *  \throw If the meshes do not share the node coordinates array.
8021  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
8022  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8023  */
8024 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
8025 {
8026   if(meshes.empty())
8027     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
8028   for(std::size_t ii=0;ii<meshes.size();ii++)
8029     if(!meshes[ii])
8030       {
8031         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
8032         throw INTERP_KERNEL::Exception(oss.str().c_str());
8033       }
8034   const DataArrayDouble *coords=meshes.front()->getCoords();
8035   int meshDim=meshes.front()->getMeshDimension();
8036   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8037   int meshLgth=0;
8038   int meshIndexLgth=0;
8039   for(;iter!=meshes.end();iter++)
8040     {
8041       if(coords!=(*iter)->getCoords())
8042         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8043       if(meshDim!=(*iter)->getMeshDimension())
8044         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8045       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
8046       meshIndexLgth+=(*iter)->getNumberOfCells();
8047     }
8048   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
8049   nodal->alloc(meshLgth,1);
8050   int *nodalPtr=nodal->getPointer();
8051   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
8052   nodalIndex->alloc(meshIndexLgth+1,1);
8053   int *nodalIndexPtr=nodalIndex->getPointer();
8054   int offset=0;
8055   for(iter=meshes.begin();iter!=meshes.end();iter++)
8056     {
8057       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8058       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8059       int nbOfCells=(*iter)->getNumberOfCells();
8060       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
8061       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8062       if(iter!=meshes.begin())
8063         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8064       else
8065         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8066       offset+=meshLgth2;
8067     }
8068   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8069   ret->setName("merge");
8070   ret->setMeshDimension(meshDim);
8071   ret->setConnectivity(nodal,nodalIndex,true);
8072   ret->setCoords(coords);
8073   return ret;
8074 }
8075
8076 /*!
8077  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8078  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8079  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8080  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8081  * New" mode are returned for each input mesh.
8082  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8083  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8084  *          valid values [0,1,2], see zipConnectivityTraducer().
8085  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8086  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8087  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8088  *          no more needed.
8089  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8090  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8091  *          is no more needed.
8092  *  \throw If \a meshes.size() == 0.
8093  *  \throw If \a meshes[ *i* ] == NULL.
8094  *  \throw If the meshes do not share the node coordinates array.
8095  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8096  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8097  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8098  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8099  */
8100 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8101 {
8102   //All checks are delegated to MergeUMeshesOnSameCoords
8103   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8104   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8105   corr.resize(meshes.size());
8106   std::size_t nbOfMeshes=meshes.size();
8107   int offset=0;
8108   const int *o2nPtr=o2n->getConstPointer();
8109   for(std::size_t i=0;i<nbOfMeshes;i++)
8110     {
8111       DataArrayInt *tmp=DataArrayInt::New();
8112       int curNbOfCells=meshes[i]->getNumberOfCells();
8113       tmp->alloc(curNbOfCells,1);
8114       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8115       offset+=curNbOfCells;
8116       tmp->setName(meshes[i]->getName());
8117       corr[i]=tmp;
8118     }
8119   return ret.retn();
8120 }
8121
8122 /*!
8123  * Makes all given meshes share the nodal connectivity array. The common connectivity
8124  * array is created by concatenating the connectivity arrays of all given meshes. All
8125  * the given meshes must be of the same space dimension but dimension of cells **can
8126  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8127  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8128  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8129  *  \param [in,out] meshes - a vector of meshes to update.
8130  *  \throw If any of \a meshes is NULL.
8131  *  \throw If the coordinates array is not set in any of \a meshes.
8132  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8133  *  \throw If \a meshes are of different space dimension.
8134  */
8135 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8136 {
8137   std::size_t sz=meshes.size();
8138   if(sz==0 || sz==1)
8139     return;
8140   std::vector< const DataArrayDouble * > coords(meshes.size());
8141   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8142   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8143     {
8144       if((*it))
8145         {
8146           (*it)->checkConnectivityFullyDefined();
8147           const DataArrayDouble *coo=(*it)->getCoords();
8148           if(coo)
8149             *it2=coo;
8150           else
8151             {
8152               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8153               oss << " has no coordinate array defined !";
8154               throw INTERP_KERNEL::Exception(oss.str().c_str());
8155             }
8156         }
8157       else
8158         {
8159           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8160           oss << " is null !";
8161           throw INTERP_KERNEL::Exception(oss.str().c_str());
8162         }
8163     }
8164   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8165   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8166   int offset=(*it)->getNumberOfNodes();
8167   (*it++)->setCoords(res);
8168   for(;it!=meshes.end();it++)
8169     {
8170       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8171       (*it)->setCoords(res);
8172       (*it)->shiftNodeNumbersInConn(offset);
8173       offset+=oldNumberOfNodes;
8174     }
8175 }
8176
8177 /*!
8178  * Merges nodes coincident with a given precision within all given meshes that share
8179  * the nodal connectivity array. The given meshes **can be of different** mesh
8180  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8181  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8182  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8183  *  \param [in,out] meshes - a vector of meshes to update.
8184  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8185  *  \throw If any of \a meshes is NULL.
8186  *  \throw If the \a meshes do not share the same node coordinates array.
8187  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8188  */
8189 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8190 {
8191   if(meshes.empty())
8192     return ;
8193   std::set<const DataArrayDouble *> s;
8194   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8195     {
8196       if(*it)
8197         s.insert((*it)->getCoords());
8198       else
8199         {
8200           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 !";
8201           throw INTERP_KERNEL::Exception(oss.str().c_str());
8202         }
8203     }
8204   if(s.size()!=1)
8205     {
8206       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 !";
8207       throw INTERP_KERNEL::Exception(oss.str().c_str());
8208     }
8209   const DataArrayDouble *coo=*(s.begin());
8210   if(!coo)
8211     return;
8212   //
8213   DataArrayInt *comm,*commI;
8214   coo->findCommonTuples(eps,-1,comm,commI);
8215   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
8216   int oldNbOfNodes=coo->getNumberOfTuples();
8217   int newNbOfNodes;
8218   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8219   if(oldNbOfNodes==newNbOfNodes)
8220     return ;
8221   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8222   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8223     {
8224       (*it)->renumberNodesInConn(o2n->getConstPointer());
8225       (*it)->setCoords(newCoords);
8226     } 
8227 }
8228
8229 /*!
8230  * 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.
8231  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8232  * \param isQuad specifies the policy of connectivity.
8233  * @ret in/out parameter in which the result will be append
8234  */
8235 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8236 {
8237   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8238   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8239   ret.push_back(cm.getExtrudedType());
8240   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8241   switch(flatType)
8242   {
8243     case INTERP_KERNEL::NORM_POINT1:
8244       {
8245         ret.push_back(connBg[1]);
8246         ret.push_back(connBg[1]+nbOfNodesPerLev);
8247         break;
8248       }
8249     case INTERP_KERNEL::NORM_SEG2:
8250       {
8251         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8252         ret.insert(ret.end(),conn,conn+4);
8253         break;
8254       }
8255     case INTERP_KERNEL::NORM_SEG3:
8256       {
8257         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8258         ret.insert(ret.end(),conn,conn+8);
8259         break;
8260       }
8261     case INTERP_KERNEL::NORM_QUAD4:
8262       {
8263         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8264         ret.insert(ret.end(),conn,conn+8);
8265         break;
8266       }
8267     case INTERP_KERNEL::NORM_TRI3:
8268       {
8269         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8270         ret.insert(ret.end(),conn,conn+6);
8271         break;
8272       }
8273     case INTERP_KERNEL::NORM_TRI6:
8274       {
8275         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,
8276           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8277         ret.insert(ret.end(),conn,conn+15);
8278         break;
8279       }
8280     case INTERP_KERNEL::NORM_QUAD8:
8281       {
8282         int conn[20]={
8283           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8284           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8285           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8286         };
8287         ret.insert(ret.end(),conn,conn+20);
8288         break;
8289       }
8290     case INTERP_KERNEL::NORM_POLYGON:
8291       {
8292         std::back_insert_iterator< std::vector<int> > ii(ret);
8293         std::copy(connBg+1,connEnd,ii);
8294         *ii++=-1;
8295         std::reverse_iterator<const int *> rConnBg(connEnd);
8296         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8297         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8298         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8299         for(std::size_t i=0;i<nbOfRadFaces;i++)
8300           {
8301             *ii++=-1;
8302             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8303             std::copy(conn,conn+4,ii);
8304           }
8305         break;
8306       }
8307     default:
8308       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8309   }
8310 }
8311
8312 /*!
8313  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8314  */
8315 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8316 {
8317   std::size_t i, ip1;
8318   double v[3]={0.,0.,0.};
8319   std::size_t sz=std::distance(begin,end);
8320   if(isQuadratic)
8321     sz/=2;
8322   for(i=0;i<sz;i++)
8323     {
8324       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];
8325       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8326       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8327     }
8328   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8329
8330   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8331   // SEG3 forming a circle):
8332   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8333     {
8334       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8335       for(std::size_t j=0;j<sz;j++)
8336         {
8337           if (j%2)  // current point i is quadratic, next point i+1 is standard
8338             {
8339               i = sz+j;
8340               ip1 = (j+1)%sz; // ip1 = "i+1"
8341             }
8342           else      // current point i is standard, next point i+1 is quadratic
8343             {
8344               i = j;
8345               ip1 = j+sz;
8346             }
8347           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8348           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8349           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8350         }
8351       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8352     }
8353   return (ret>0.);
8354 }
8355
8356 /*!
8357  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8358  */
8359 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8360 {
8361   std::vector<std::pair<int,int> > edges;
8362   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8363   const int *bgFace=begin;
8364   for(std::size_t i=0;i<nbOfFaces;i++)
8365     {
8366       const int *endFace=std::find(bgFace+1,end,-1);
8367       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8368       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8369         {
8370           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8371           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8372             return false;
8373           edges.push_back(p1);
8374         }
8375       bgFace=endFace+1;
8376     }
8377   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8378 }
8379
8380 /*!
8381  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8382  */
8383 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8384 {
8385   double vec0[3],vec1[3];
8386   std::size_t sz=std::distance(begin,end);
8387   if(sz%2!=0)
8388     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8389   int nbOfNodes=(int)sz/2;
8390   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8391   const double *pt0=coords+3*begin[0];
8392   const double *pt1=coords+3*begin[nbOfNodes];
8393   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8394   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8395 }
8396
8397 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8398 {
8399   std::size_t sz=std::distance(begin,end);
8400   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8401   std::size_t nbOfNodes(sz/2);
8402   std::copy(begin,end,(int *)tmp);
8403   for(std::size_t j=1;j<nbOfNodes;j++)
8404     {
8405       begin[j]=tmp[nbOfNodes-j];
8406       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8407     }
8408 }
8409
8410 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8411 {
8412   std::size_t sz=std::distance(begin,end);
8413   if(sz!=4)
8414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
8415   double vec0[3],vec1[3];
8416   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8417   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]; 
8418   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;
8419 }
8420
8421 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8422 {
8423   std::size_t sz=std::distance(begin,end);
8424   if(sz!=5)
8425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
8426   double vec0[3];
8427   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8428   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8429   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8430 }
8431
8432 /*!
8433  * 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 ) 
8434  * 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
8435  * a 2D space.
8436  *
8437  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8438  * \param [in] coords the coordinates with nb of components exactly equal to 3
8439  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8440  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8441  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8442  */
8443 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8444 {
8445   int nbFaces=std::count(begin+1,end,-1)+1;
8446   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8447   double *vPtr=v->getPointer();
8448   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8449   double *pPtr=p->getPointer();
8450   const int *stFaceConn=begin+1;
8451   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8452     {
8453       const int *endFaceConn=std::find(stFaceConn,end,-1);
8454       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8455       stFaceConn=endFaceConn+1;
8456     }
8457   pPtr=p->getPointer(); vPtr=v->getPointer();
8458   DataArrayInt *comm1=0,*commI1=0;
8459   v->findCommonTuples(eps,-1,comm1,commI1);
8460   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8461   const int *comm1Ptr=comm1->getConstPointer();
8462   const int *commI1Ptr=commI1->getConstPointer();
8463   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8464   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8465   //
8466   MCAuto<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8467   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8468   mm->finishInsertingCells();
8469   //
8470   for(int i=0;i<nbOfGrps1;i++)
8471     {
8472       int vecId=comm1Ptr[commI1Ptr[i]];
8473       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8474       DataArrayInt *comm2=0,*commI2=0;
8475       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8476       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8477       const int *comm2Ptr=comm2->getConstPointer();
8478       const int *commI2Ptr=commI2->getConstPointer();
8479       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8480       for(int j=0;j<nbOfGrps2;j++)
8481         {
8482           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8483             {
8484               res->insertAtTheEnd(begin,end);
8485               res->pushBackSilent(-1);
8486             }
8487           else
8488             {
8489               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8490               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
8491               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8492               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8493               MCAuto<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8494               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8495               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8496               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8497               const int *idsNodePtr=idsNode->getConstPointer();
8498               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];
8499               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8500               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8501               if(std::abs(norm)>eps)
8502                 {
8503                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8504                   mm3->rotate(center,vec,angle);
8505                 }
8506               mm3->changeSpaceDimension(2);
8507               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8508               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8509               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8510               int nbOfCells=mm4->getNumberOfCells();
8511               for(int k=0;k<nbOfCells;k++)
8512                 {
8513                   int l=0;
8514                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8515                     res->pushBackSilent(idsNodePtr[*work]);
8516                   res->pushBackSilent(-1);
8517                 }
8518             }
8519         }
8520     }
8521   res->popBackSilent();
8522 }
8523
8524 /*!
8525  * 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
8526  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8527  * 
8528  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8529  * \param [in] coords coordinates expected to have 3 components.
8530  * \param [in] begin start of the nodal connectivity of the face.
8531  * \param [in] end end of the nodal connectivity (excluded) of the face.
8532  * \param [out] v the normalized vector of size 3
8533  * \param [out] p the pos of plane
8534  */
8535 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8536 {
8537   std::size_t nbPoints=std::distance(begin,end);
8538   if(nbPoints<3)
8539     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8540   double vec[3]={0.,0.,0.};
8541   std::size_t j=0;
8542   bool refFound=false;
8543   for(;j<nbPoints-1 && !refFound;j++)
8544     {
8545       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8546       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8547       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8548       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8549       if(norm>eps)
8550         {
8551           refFound=true;
8552           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8553         }
8554     }
8555   for(std::size_t i=j;i<nbPoints-1;i++)
8556     {
8557       double curVec[3];
8558       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8559       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8560       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8561       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8562       if(norm<eps)
8563         continue;
8564       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8565       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];
8566       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8567       if(norm>eps)
8568         {
8569           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8570           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8571           return ;
8572         }
8573     }
8574   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8575 }
8576
8577 /*!
8578  * This method tries to obtain a well oriented polyhedron.
8579  * If the algorithm fails, an exception will be thrown.
8580  */
8581 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8582 {
8583   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8584   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8585   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8586   isPerm[0]=true;
8587   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8588   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8589   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8590   //
8591   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8592     {
8593       bgFace=begin;
8594       std::size_t smthChanged=0;
8595       for(std::size_t i=0;i<nbOfFaces;i++)
8596         {
8597           endFace=std::find(bgFace+1,end,-1);
8598           nbOfEdgesInFace=std::distance(bgFace,endFace);
8599           if(!isPerm[i])
8600             {
8601               bool b;
8602               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8603                 {
8604                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8605                   std::pair<int,int> p2(p1.second,p1.first);
8606                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8607                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8608                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8609                 }
8610               if(isPerm[i])
8611                 { 
8612                   if(!b)
8613                     std::reverse(bgFace+1,endFace);
8614                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8615                     {
8616                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8617                       std::pair<int,int> p2(p1.second,p1.first);
8618                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8619                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8620                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8621                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8622                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8623                       if(it!=edgesOK.end())
8624                         {
8625                           edgesOK.erase(it);
8626                           edgesFinished.push_back(p1);
8627                         }
8628                       else
8629                         edgesOK.push_back(p1);
8630                     }
8631                 }
8632             }
8633           bgFace=endFace+1;
8634         }
8635       if(smthChanged==0)
8636         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8637     }
8638   if(!edgesOK.empty())
8639     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8640   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8641     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8642       bgFace=begin;
8643       for(std::size_t i=0;i<nbOfFaces;i++)
8644         {
8645           endFace=std::find(bgFace+1,end,-1);
8646           std::reverse(bgFace+1,endFace);
8647           bgFace=endFace+1;
8648         }
8649     }
8650 }
8651
8652 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8653 {
8654   int nbOfNodesExpected(skin->getNumberOfNodes());
8655   const int *n2oPtr(n2o->getConstPointer());
8656   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8657   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8658   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8659   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8660   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8661   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8662   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8663   if(nbOfNodesExpected<1)
8664     return ret.retn();
8665   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8666   *work++=n2oPtr[prevNode];
8667   for(int i=1;i<nbOfNodesExpected;i++)
8668     {
8669       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8670         {
8671           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8672           conn.erase(prevNode);
8673           if(conn.size()==1)
8674             {
8675               int curNode(*(conn.begin()));
8676               *work++=n2oPtr[curNode];
8677               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8678               shar.erase(prevCell);
8679               if(shar.size()==1)
8680                 {
8681                   prevCell=*(shar.begin());
8682                   prevNode=curNode;
8683                 }
8684               else
8685                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8686             }
8687           else
8688             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8689         }
8690       else
8691         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8692     }
8693   return ret.retn();
8694 }
8695
8696 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8697 {
8698   int nbOfNodesExpected(skin->getNumberOfNodes());
8699   int nbOfTurn(nbOfNodesExpected/2);
8700   const int *n2oPtr(n2o->getConstPointer());
8701   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8702   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8703   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8704   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8705   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8706   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8707   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8708   if(nbOfNodesExpected<1)
8709     return ret.retn();
8710   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8711   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8712   for(int i=1;i<nbOfTurn;i++)
8713     {
8714       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8715         {
8716           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8717           conn.erase(prevNode);
8718           if(conn.size()==1)
8719             {
8720               int curNode(*(conn.begin()));
8721               *work=n2oPtr[curNode];
8722               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8723               shar.erase(prevCell);
8724               if(shar.size()==1)
8725                 {
8726                   int curCell(*(shar.begin()));
8727                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8728                   prevCell=curCell;
8729                   prevNode=curNode;
8730                   work++;
8731                 }
8732               else
8733                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8734             }
8735           else
8736             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8737         }
8738       else
8739         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8740     }
8741   return ret.retn();
8742 }
8743
8744 /*!
8745  * This method makes the assumption spacedimension == meshdimension == 2.
8746  * This method works only for linear cells.
8747  * 
8748  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8749  */
8750 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8751 {
8752   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8753     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8754   MCAuto<MEDCouplingUMesh> skin(computeSkin());
8755   int oldNbOfNodes(skin->getNumberOfNodes());
8756   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
8757   int nbOfNodesExpected(skin->getNumberOfNodes());
8758   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8759   int nbCells(skin->getNumberOfCells());
8760   if(nbCells==nbOfNodesExpected)
8761     return buildUnionOf2DMeshLinear(skin,n2o);
8762   else if(2*nbCells==nbOfNodesExpected)
8763     return buildUnionOf2DMeshQuadratic(skin,n2o);
8764   else
8765     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8766 }
8767
8768 /*!
8769  * This method makes the assumption spacedimension == meshdimension == 3.
8770  * This method works only for linear cells.
8771  * 
8772  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8773  */
8774 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8775 {
8776   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8778   MCAuto<MEDCouplingUMesh> m=computeSkin();
8779   const int *conn=m->getNodalConnectivity()->getConstPointer();
8780   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8781   int nbOfCells=m->getNumberOfCells();
8782   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8783   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8784   if(nbOfCells<1)
8785     return ret.retn();
8786   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8787   for(int i=1;i<nbOfCells;i++)
8788     {
8789       *work++=-1;
8790       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8791     }
8792   return ret.retn();
8793 }
8794
8795 /*!
8796  * \brief Creates a graph of cell neighbors
8797  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8798  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8799  *  For example
8800  *  - index:  0 3 5 6 6
8801  *  - value:  1 2 3 2 3 3
8802  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8803  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8804  */
8805 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8806 {
8807   checkConnectivityFullyDefined();
8808
8809   int meshDim = this->getMeshDimension();
8810   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
8811   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
8812   this->getReverseNodalConnectivity(revConn,indexr);
8813   const int* indexr_ptr=indexr->getConstPointer();
8814   const int* revConn_ptr=revConn->getConstPointer();
8815
8816   const MEDCoupling::DataArrayInt* index;
8817   const MEDCoupling::DataArrayInt* conn;
8818   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8819   index=this->getNodalConnectivityIndex();
8820   int nbCells=this->getNumberOfCells();
8821   const int* index_ptr=index->getConstPointer();
8822   const int* conn_ptr=conn->getConstPointer();
8823
8824   //creating graph arcs (cell to cell relations)
8825   //arcs are stored in terms of (index,value) notation
8826   // 0 3 5 6 6
8827   // 1 2 3 2 3 3
8828   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8829   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8830
8831   //warning here one node have less than or equal effective number of cell with it
8832   //but cell could have more than effective nodes
8833   //because other equals nodes in other domain (with other global inode)
8834   std::vector <int> cell2cell_index(nbCells+1,0);
8835   std::vector <int> cell2cell;
8836   cell2cell.reserve(3*nbCells);
8837
8838   for (int icell=0; icell<nbCells;icell++)
8839     {
8840       std::map<int,int > counter;
8841       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8842         {
8843           int inode=conn_ptr[iconn];
8844           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8845             {
8846               int icell2=revConn_ptr[iconnr];
8847               std::map<int,int>::iterator iter=counter.find(icell2);
8848               if (iter!=counter.end()) (iter->second)++;
8849               else counter.insert(std::make_pair(icell2,1));
8850             }
8851         }
8852       for (std::map<int,int>::const_iterator iter=counter.begin();
8853            iter!=counter.end(); iter++)
8854         if (iter->second >= meshDim)
8855           {
8856             cell2cell_index[icell+1]++;
8857             cell2cell.push_back(iter->first);
8858           }
8859     }
8860   indexr->decrRef();
8861   revConn->decrRef();
8862   cell2cell_index[0]=0;
8863   for (int icell=0; icell<nbCells;icell++)
8864     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8865
8866   //filling up index and value to create skylinearray structure
8867   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8868   return array;
8869 }
8870
8871 /*!
8872  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8873  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8874  */
8875 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8876 {
8877   double *w=zipFrmt;
8878   if(spaceDim==3)
8879     for(int i=0;i<nbOfNodesInCell;i++)
8880       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8881   else if(spaceDim==2)
8882     {
8883       for(int i=0;i<nbOfNodesInCell;i++)
8884         {
8885           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8886           *w++=0.;
8887         }
8888     }
8889   else
8890     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8891 }
8892
8893 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8894 {
8895   int nbOfCells=getNumberOfCells();
8896   if(nbOfCells<=0)
8897     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8898   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};
8899   ofs << "  <" << getVTKDataSetType() << ">\n";
8900   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8901   ofs << "      <PointData>\n" << pointData << std::endl;
8902   ofs << "      </PointData>\n";
8903   ofs << "      <CellData>\n" << cellData << std::endl;
8904   ofs << "      </CellData>\n";
8905   ofs << "      <Points>\n";
8906   if(getSpaceDimension()==3)
8907     _coords->writeVTK(ofs,8,"Points",byteData);
8908   else
8909     {
8910       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8911       coo->writeVTK(ofs,8,"Points",byteData);
8912     }
8913   ofs << "      </Points>\n";
8914   ofs << "      <Cells>\n";
8915   const int *cPtr=_nodal_connec->getConstPointer();
8916   const int *cIPtr=_nodal_connec_index->getConstPointer();
8917   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8918   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8919   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8920   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8921   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8922   int szFaceOffsets=0,szConn=0;
8923   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8924     {
8925       *w2=cPtr[cIPtr[i]];
8926       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8927         {
8928           *w1=-1;
8929           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8930           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8931         }
8932       else
8933         {
8934           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8935           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8936           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8937           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8938           w4=std::copy(c.begin(),c.end(),w4);
8939         }
8940     }
8941   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8942   types->writeVTK(ofs,8,"UInt8","types",byteData);
8943   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8944   if(szFaceOffsets!=0)
8945     {//presence of Polyhedra
8946       connectivity->reAlloc(szConn);
8947       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8948       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8949       w1=faces->getPointer();
8950       for(int i=0;i<nbOfCells;i++)
8951         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8952           {
8953             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8954             *w1++=nbFaces;
8955             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8956             for(int j=0;j<nbFaces;j++)
8957               {
8958                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8959                 *w1++=(int)std::distance(w6,w5);
8960                 w1=std::copy(w6,w5,w1);
8961                 w6=w5+1;
8962               }
8963           }
8964       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8965     }
8966   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8967   ofs << "      </Cells>\n";
8968   ofs << "    </Piece>\n";
8969   ofs << "  </" << getVTKDataSetType() << ">\n";
8970 }
8971
8972 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8973 {
8974   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8975   if(_mesh_dim==-2)
8976     { stream << " Not set !"; return ; }
8977   stream << " Mesh dimension : " << _mesh_dim << ".";
8978   if(_mesh_dim==-1)
8979     return ;
8980   if(!_coords)
8981     { stream << " No coordinates set !"; return ; }
8982   if(!_coords->isAllocated())
8983     { stream << " Coordinates set but not allocated !"; return ; }
8984   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8985   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8986   if(!_nodal_connec_index)
8987     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8988   if(!_nodal_connec_index->isAllocated())
8989     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8990   int lgth=_nodal_connec_index->getNumberOfTuples();
8991   int cpt=_nodal_connec_index->getNumberOfComponents();
8992   if(cpt!=1 || lgth<1)
8993     return ;
8994   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8995 }
8996
8997 std::string MEDCouplingUMesh::getVTKDataSetType() const
8998 {
8999   return std::string("UnstructuredGrid");
9000 }
9001
9002 std::string MEDCouplingUMesh::getVTKFileExtension() const
9003 {
9004   return std::string("vtu");
9005 }
9006
9007 /*!
9008  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
9009  * returns a result mesh constituted by polygons.
9010  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
9011  * all nodes from m2.
9012  * The meshes should be in 2D space. In
9013  * addition, returns two arrays mapping cells of the result mesh to cells of the input
9014  * meshes.
9015  *  \param [in] m1 - the first input mesh which is a partitioned object. The mesh must be so that each point in the space covered by \a m1
9016  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9017  *  \param [in] m2 - the second input mesh which is a partition tool. The mesh must be so that each point in the space covered by \a m2
9018  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9019  *  \param [in] eps - precision used to detect coincident mesh entities.
9020  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
9021  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
9022  *         this array using decrRef() as it is no more needed.
9023  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
9024  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
9025  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
9026  *         any cell of \a m2. The caller is to delete this array using decrRef() as
9027  *         it is no more needed.  
9028  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
9029  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
9030  *         is no more needed.  
9031  *  \throw If the coordinates array is not set in any of the meshes.
9032  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
9033  *  \throw If any of the meshes is not a 2D mesh in 2D space.
9034  *
9035  *  \sa conformize2D, mergeNodes
9036  */
9037 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9038                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9039 {
9040   if(!m1 || !m2)
9041     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9042   m1->checkFullyDefined();
9043   m2->checkFullyDefined();
9044   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9045     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9046
9047   // Step 1: compute all edge intersections (new nodes)
9048   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9049   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9050   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9051   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9052   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9053                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9054                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9055   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9056   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9057   MCAuto<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9058
9059   // Step 2: re-order newly created nodes according to the ordering found in m2
9060   std::vector< std::vector<int> > intersectEdge2;
9061   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9062   subDiv2.clear(); dd5=0; dd6=0;
9063
9064   // Step 3:
9065   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9066   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9067   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9068                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9069
9070   // Step 4: Prepare final result:
9071   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9072   addCooDa->alloc((int)(addCoo.size())/2,2);
9073   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9074   MCAuto<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9075   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9076   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9077   std::vector<const DataArrayDouble *> coordss(4);
9078   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9079   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9080   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9081   MCAuto<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9082   MCAuto<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9083   MCAuto<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9084   MCAuto<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9085   ret->setConnectivity(conn,connI,true);
9086   ret->setCoords(coo);
9087   cellNb1=c1.retn(); cellNb2=c2.retn();
9088   return ret.retn();
9089 }
9090
9091 /// @cond INTERNAL
9092
9093 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9094 {
9095   if(candidates.empty())
9096     return false;
9097   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9098     {
9099       const std::vector<int>& pool(intersectEdge1[*it]);
9100       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9101       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9102         {
9103           retVal=*it+1;
9104           return true;
9105         }
9106       tmp[0]=stop; tmp[1]=start;
9107       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9108         {
9109           retVal=-*it-1;
9110           return true;
9111         }
9112     }
9113   return false;
9114 }
9115
9116 MEDCouplingUMesh *BuildMesh1DCutFrom(const MEDCouplingUMesh *mesh1D, const std::vector< std::vector<int> >& intersectEdge2, const DataArrayDouble *coords1, const std::vector<double>& addCoo, const std::map<int,int>& mergedNodes, const std::vector< std::vector<int> >& colinear2, const std::vector< std::vector<int> >& intersectEdge1,
9117                                      MCAuto<DataArrayInt>& idsInRetColinear, MCAuto<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9118 {
9119   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9120   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9121   int nCells(mesh1D->getNumberOfCells());
9122   if(nCells!=(int)intersectEdge2.size())
9123     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9124   const DataArrayDouble *coo2(mesh1D->getCoords());
9125   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9126   const double *coo2Ptr(coo2->begin());
9127   int offset1(coords1->getNumberOfTuples());
9128   int offset2(offset1+coo2->getNumberOfTuples());
9129   int offset3(offset2+addCoo.size()/2);
9130   std::vector<double> addCooQuad;
9131   MCAuto<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9132   int tmp[4],cicnt(0),kk(0);
9133   for(int i=0;i<nCells;i++)
9134     {
9135       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
9136       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9137       const std::vector<int>& subEdges(intersectEdge2[i]);
9138       int nbSubEdge(subEdges.size()/2);
9139       for(int j=0;j<nbSubEdge;j++,kk++)
9140         {
9141           MCAuto<INTERP_KERNEL::Node> n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
9142           MCAuto<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9143           INTERP_KERNEL::Edge *e2Ptr(e2);
9144           std::map<int,int>::const_iterator itm;
9145           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9146             {
9147               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9148               itm=mergedNodes.find(subEdges[2*j]);
9149               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9150               itm=mergedNodes.find(subEdges[2*j+1]);
9151               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9152               tmp[3]=offset3+(int)addCooQuad.size()/2;
9153               double tmp2[2];
9154               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9155               cicnt+=4;
9156               cOut->insertAtTheEnd(tmp,tmp+4);
9157               ciOut->pushBackSilent(cicnt);
9158             }
9159           else
9160             {
9161               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9162               itm=mergedNodes.find(subEdges[2*j]);
9163               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9164               itm=mergedNodes.find(subEdges[2*j+1]);
9165               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9166               cicnt+=3;
9167               cOut->insertAtTheEnd(tmp,tmp+3);
9168               ciOut->pushBackSilent(cicnt);
9169             }
9170           int tmp00;
9171           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9172             {
9173               idsInRetColinear->pushBackSilent(kk);
9174               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9175             }
9176         }
9177       e->decrRef();
9178     }
9179   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9180   ret->setConnectivity(cOut,ciOut,true);
9181   MCAuto<DataArrayDouble> arr3(DataArrayDouble::New());
9182   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9183   MCAuto<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9184   std::vector<const DataArrayDouble *> coordss(4);
9185   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9186   MCAuto<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9187   ret->setCoords(arr);
9188   return ret.retn();
9189 }
9190
9191 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9192 {
9193   std::vector<int> allEdges;
9194   for(const int *it2(descBg);it2!=descEnd;it2++)
9195     {
9196       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9197       if(*it2>0)
9198         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9199       else
9200         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9201     }
9202   std::size_t nb(allEdges.size());
9203   if(nb%2!=0)
9204     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9205   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9206   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9207   ret->setCoords(coords);
9208   ret->allocateCells(1);
9209   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9210   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9211     connOut[kk]=allEdges[2*kk];
9212   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9213   return ret.retn();
9214 }
9215
9216 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9217 {
9218   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9219   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9220   std::size_t ii(0);
9221   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9222   if(sz!=std::distance(descBg,descEnd))
9223     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9224   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9225   std::vector<int> allEdges,centers;
9226   const double *coordsPtr(coords->begin());
9227   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9228   int offset(coords->getNumberOfTuples());
9229   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9230     {
9231       INTERP_KERNEL::NormalizedCellType typeOfSon;
9232       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9233       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9234       if(*it2>0)
9235         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9236       else
9237         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9238       if(edge1.size()==2)
9239         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9240       else
9241         {//the current edge has been subsplit -> create corresponding centers.
9242           std::size_t nbOfCentersToAppend(edge1.size()/2);
9243           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9244           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9245           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9246           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9247             {
9248               double tmpp[2];
9249               const double *aa(coordsPtr+2*(*it3++));
9250               const double *bb(coordsPtr+2*(*it3++));
9251               ee->getMiddleOfPoints(aa,bb,tmpp);
9252               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9253               centers.push_back(offset+k);
9254             }
9255         }
9256     }
9257   std::size_t nb(allEdges.size());
9258   if(nb%2!=0)
9259     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9260   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9261   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9262   if(addCoo->empty())
9263     ret->setCoords(coords);
9264   else
9265     {
9266       addCoo->rearrange(2);
9267       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9268       ret->setCoords(addCoo);
9269     }
9270   ret->allocateCells(1);
9271   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9272   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9273     connOut[kk]=allEdges[2*kk];
9274   connOut.insert(connOut.end(),centers.begin(),centers.end());
9275   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9276   return ret.retn();
9277 }
9278
9279 /*!
9280  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9281  * of those edges.
9282  *
9283  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9284  */
9285 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9286 {
9287   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9288   if(!cm.isQuadratic())
9289     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9290   else
9291     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9292 }
9293
9294 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edges)
9295 {
9296   bool isQuad(false);
9297   for(std::vector< MCAuto<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9298     {
9299       const INTERP_KERNEL::Edge *ee(*it);
9300       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9301         isQuad=true;
9302     }
9303   if(!isQuad)
9304     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9305   else
9306     {
9307       const double *coo(mesh2D->getCoords()->begin());
9308       std::size_t sz(conn.size());
9309       std::vector<double> addCoo;
9310       std::vector<int> conn2(conn);
9311       int offset(mesh2D->getNumberOfNodes());
9312       for(std::size_t i=0;i<sz;i++)
9313         {
9314           double tmp[2];
9315           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9316           addCoo.insert(addCoo.end(),tmp,tmp+2);
9317           conn2.push_back(offset+(int)i);
9318         }
9319       mesh2D->getCoords()->rearrange(1);
9320       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9321       mesh2D->getCoords()->rearrange(2);
9322       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9323     }
9324 }
9325
9326 /*!
9327  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9328  *
9329  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9330  * a set of edges defined in \a splitMesh1D.
9331  */
9332 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edge1BisPtr,
9333                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& out1)
9334 {
9335   std::size_t nb(edge1Bis.size()/2);
9336   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9337   int iEnd(splitMesh1D->getNumberOfCells());
9338   if(iEnd==0)
9339     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9340   std::size_t ii,jj;
9341   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9342   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9343   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9344   //
9345   if(jj==nb)
9346     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9347       out0.resize(1); out1.resize(1);
9348       std::vector<int>& connOut(out0[0]);
9349       connOut.resize(nbOfEdgesOf2DCellSplit);
9350       std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9351       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9352       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9353         {
9354           connOut[kk]=edge1Bis[2*kk];
9355           edgesPtr[kk]=edge1BisPtr[2*kk];
9356         }
9357     }
9358   else
9359     {
9360       // [i,iEnd[ contains the
9361       out0.resize(2); out1.resize(2);
9362       std::vector<int>& connOutLeft(out0[0]);
9363       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9364       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9365       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eright(out1[1]);
9366       for(std::size_t k=ii;k<jj+1;k++)
9367         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9368       std::vector< MCAuto<INTERP_KERNEL::Edge> > ees(iEnd);
9369       for(int ik=0;ik<iEnd;ik++)
9370         {
9371           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9372           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9373           ees[ik]=ee;
9374         }
9375       for(int ik=iEnd-1;ik>=0;ik--)
9376         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9377       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9378         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9379       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9380       for(int ik=0;ik<iEnd;ik++)
9381         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9382       eright.insert(eright.end(),ees.begin(),ees.end());
9383     }
9384 }
9385
9386 /// @endcond
9387
9388 /// @cond INTERNAL
9389
9390 struct CellInfo
9391 {
9392 public:
9393   CellInfo() { }
9394   CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9395 public:
9396   std::vector<int> _edges;
9397   std::vector< MCAuto<INTERP_KERNEL::Edge> > _edges_ptr;
9398 };
9399
9400 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr)
9401 {
9402   std::size_t nbe(edges.size());
9403   std::vector<int> edges2(2*nbe); std::vector< MCAuto<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9404   for(std::size_t i=0;i<nbe;i++)
9405     {
9406       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9407       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9408     }
9409   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9410   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9411   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9412 }
9413
9414 class EdgeInfo
9415 {
9416 public:
9417   EdgeInfo(int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9418   EdgeInfo(int istart, int iend, int pos, const MCAuto<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9419   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9420   void somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9421   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9422 private:
9423   int _istart;
9424   int _iend;
9425   MCAuto<MEDCouplingUMesh> _mesh;
9426   MCAuto<INTERP_KERNEL::Edge> _edge;
9427   int _left;
9428   int _right;
9429 };
9430
9431 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9432 {
9433   const MEDCouplingUMesh *mesh(_mesh);
9434   if(mesh)
9435     return ;
9436   if(_right<pos)
9437     return ;
9438   if(_left>pos)
9439     { _left++; _right++; return ; }
9440   if(_right==pos)
9441     {
9442       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9443       if((isLeft && isRight) || (!isLeft && !isRight))
9444         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9445       if(isLeft)
9446         return ;
9447       if(isRight)
9448         {
9449           _right++;
9450           return ;
9451         }
9452     }
9453   if(_left==pos)
9454     {
9455       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9456       if((isLeft && isRight) || (!isLeft && !isRight))
9457         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9458       if(isLeft)
9459         {
9460           _right++;
9461           return ;
9462         }
9463       if(isRight)
9464         {
9465           _left++;
9466           _right++;
9467           return ;
9468         }
9469     }
9470 }
9471
9472 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9473 {
9474   const MEDCouplingUMesh *mesh(_mesh);
9475   if(!mesh)
9476     {
9477       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9478     }
9479   else
9480     {// not fully splitting cell case
9481       if(mesh2D->getNumberOfCells()==1)
9482         {//little optimization. 1 cell no need to find in which cell mesh is !
9483           neighbors[0]=offset; neighbors[1]=offset;
9484           return;
9485         }
9486       else
9487         {
9488           MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9489           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9490           if(cellId==-1)
9491             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9492           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9493         }
9494     }
9495 }
9496
9497 class VectorOfCellInfo
9498 {
9499 public:
9500   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9501   std::size_t size() const { return _pool.size(); }
9502   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9503   void setMeshAt(int pos, const MCAuto<MEDCouplingUMesh>& mesh, int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& edgePtrs);
9504   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9505   const std::vector< MCAuto<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9506   MCAuto<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9507   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9508 private:
9509   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9510   void updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9511   const CellInfo& get(int pos) const;
9512   CellInfo& get(int pos);
9513 private:
9514   std::vector<CellInfo> _pool;
9515   MCAuto<MEDCouplingUMesh> _ze_mesh;
9516   std::vector<EdgeInfo> _edge_info;
9517 };
9518
9519 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9520 {
9521   _pool[0]._edges=edges;
9522   _pool[0]._edges_ptr=edgesPtr;
9523 }
9524
9525 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9526 {
9527   if(_pool.empty())
9528     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9529   if(_pool.size()==1)
9530     return 0;
9531   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9532   if(!zeMesh)
9533     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9534   MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9535   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9536 }
9537
9538 void VectorOfCellInfo::setMeshAt(int pos, const MCAuto<MEDCouplingUMesh>& mesh, int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& edgePtrs)
9539 {
9540   get(pos);//to check pos
9541   bool isFast(pos==0 && _pool.size()==1);
9542   std::size_t sz(edges.size());
9543   // dealing with edges
9544   if(sz==1)
9545     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9546   else
9547     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9548   //
9549   std::vector<CellInfo> pool(_pool.size()-1+sz);
9550   for(int i=0;i<pos;i++)
9551     pool[i]=_pool[i];
9552   for(std::size_t j=0;j<sz;j++)
9553     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9554   for(int i=pos+1;i<(int)_pool.size();i++)
9555     pool[i+sz-1]=_pool[i];
9556   _pool=pool;
9557   //
9558   if(sz==2)
9559     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9560   //
9561   if(isFast)
9562     {
9563       _ze_mesh=mesh;
9564       return ;
9565     }
9566   //
9567   std::vector< MCAuto<MEDCouplingUMesh> > ms;
9568   if(pos>0)
9569     {
9570       MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(0,pos,true)));
9571       ms.push_back(elt);
9572     }
9573   ms.push_back(mesh);
9574   if(pos<_ze_mesh->getNumberOfCells()-1)
9575   {
9576     MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(pos+1,_ze_mesh->getNumberOfCells(),true)));
9577     ms.push_back(elt);
9578   }
9579   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9580   for(std::size_t j=0;j<ms2.size();j++)
9581     ms2[j]=ms[j];
9582   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9583 }
9584
9585 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9586 {
9587   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9588 }
9589
9590 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9591 {
9592   if(pos<0)
9593     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9594   int ret(0);
9595   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9596     {
9597       if((*it).isInMyRange(pos))
9598         return ret;
9599     }
9600   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9601 }
9602
9603 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9604 {
9605   get(pos);//to check;
9606   if(_edge_info.empty())
9607     return ;
9608   std::size_t sz(_edge_info.size()-1);
9609   for(std::size_t i=0;i<sz;i++)
9610     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9611 }
9612
9613 const CellInfo& VectorOfCellInfo::get(int pos) const
9614 {
9615   if(pos<0 || pos>=(int)_pool.size())
9616     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9617   return _pool[pos];
9618 }
9619
9620 CellInfo& VectorOfCellInfo::get(int pos)
9621 {
9622   if(pos<0 || pos>=(int)_pool.size())
9623     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9624   return _pool[pos];
9625 }
9626
9627 /*!
9628  * Given :
9629  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9630  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9631  *
9632  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9633  *
9634  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9635  *
9636  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9637  */
9638 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9639                                          MCAuto<DataArrayInt>& idsLeftRight)
9640 {
9641   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9642   if(nbCellsInSplitMesh1D==0)
9643     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9644   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9645   std::size_t nb(allEdges.size()),jj;
9646   if(nb%2!=0)
9647     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9648   std::vector<int> edge1Bis(nb*2);
9649   std::vector< MCAuto<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9650   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9651   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9652   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9653   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9654   //
9655   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9656   int *idsLeftRightPtr(idsLeftRight->getPointer());
9657   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9658   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9659     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9660       int iEnd(iStart);
9661       for(;iEnd<nbCellsInSplitMesh1D;)
9662         {
9663           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9664           if(jj!=nb)
9665             break;
9666           else
9667             iEnd++;
9668         }
9669       if(iEnd<nbCellsInSplitMesh1D)
9670         iEnd++;
9671       //
9672       MCAuto<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelfSlice(iStart,iEnd,1,true)));
9673       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9674       //
9675       MCAuto<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9676       retTmp->setCoords(splitMesh1D->getCoords());
9677       retTmp->allocateCells();
9678
9679       std::vector< std::vector<int> > out0;
9680       std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > > out1;
9681
9682       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9683       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9684         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9685       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9686       //
9687       iStart=iEnd;
9688     }
9689   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9690     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9691   return pool.getZeMesh().retn();
9692 }
9693
9694 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9695                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9696                                      MCAuto<DataArrayInt>& idsLeftRight)
9697 {
9698   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9699   //
9700   std::vector<int> allEdges;
9701   std::vector< MCAuto<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9702   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9703     {
9704       int edgeId(std::abs(*it)-1);
9705       std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9706       MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9707       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9708       if(*it>0)
9709         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9710       else
9711         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9712       std::size_t sz(edge1.size());
9713       for(std::size_t cnt=0;cnt<sz;cnt++)
9714         allEdgesPtr.push_back(ee);
9715     }
9716   //
9717   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9718 }
9719
9720 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9721 {
9722   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9723     {//easy case comparison not
9724       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9725     }
9726   else if(typ1.isQuadratic() && typ2.isQuadratic())
9727     {
9728       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9729       if(!status0)
9730         return false;
9731       if(conn1[2]==conn2[2])
9732         return true;
9733       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9734       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9735       return dist<eps;
9736     }
9737   else
9738     {//only one is quadratic
9739       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9740       if(!status0)
9741         return false;
9742       const double *a(0),*bb(0),*be(0);
9743       if(typ1.isQuadratic())
9744         {
9745           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9746         }
9747       else
9748         {
9749           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9750         }
9751       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9752       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9753       return dist<eps;
9754     }
9755 }
9756
9757 /*!
9758  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9759  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9760  *
9761  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9762  */
9763 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9764 {
9765   if(candidatesIn2DEnd==candidatesIn2DBg)
9766     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9767   const double *coo(mesh2DSplit->getCoords()->begin());
9768   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9769     return *candidatesIn2DBg;
9770   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9771   MCAuto<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9772   if(cellIdInMesh1DSplitRelative<0)
9773     cur1D->changeOrientationOfCells();
9774   const int *c1D(cur1D->getNodalConnectivity()->begin());
9775   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9776   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9777     {
9778       MCAuto<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9779       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9780       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9781       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9782       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9783       for(unsigned it2=0;it2<sz;it2++)
9784         {
9785           INTERP_KERNEL::NormalizedCellType typeOfSon;
9786           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9787           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9788           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9789             return *it;
9790         }
9791     }
9792   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9793 }
9794
9795 /// @endcond
9796
9797 /*!
9798  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9799  * Thus the final result contains the aggregation of nodes of \a mesh2D, then nodes of \a mesh1D, then new nodes that are the result of the intersection
9800  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9801  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9802  *
9803  * \param [in] mesh2D - the 2D mesh (spacedim=meshdim=2) to be intersected using \a mesh1D tool. The mesh must be so that each point in the space covered by \a mesh2D
9804  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9805  * \param [in] mesh1D - the 1D mesh (spacedim=2 meshdim=1) the is the tool that will be used to intersect \a mesh2D. \a mesh1D must be ordered consecutively. If it is not the case
9806  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9807  * \param [in] eps - precision used to perform intersections and localization operations.
9808  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9809  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9810  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9811  *                               So this array has a number of tuples equal to the number of cells of \a splitMesh2D and a number of component equal to 1.
9812  * \param [out] cellIdInMesh1D - the array of pair that gives for each cell id \a i in \a splitMesh1D the cell in \a splitMesh2D on the left for the 1st component
9813  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9814  *                               So this array has a number of tuples equal to the number of cells of \a splitMesh1D and a number of components equal to 2.
9815  *
9816  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9817  */
9818 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9819 {
9820   if(!mesh2D || !mesh1D)
9821     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9822   mesh2D->checkFullyDefined();
9823   mesh1D->checkFullyDefined();
9824   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9825   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9827   // Step 1: compute all edge intersections (new nodes)
9828   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9829   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9830   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9831   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9832   //
9833   // Build desc connectivity
9834   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9835   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9836   MCAuto<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9837   std::map<int,int> mergedNodes;
9838   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9839   // use mergeNodes to fix intersectEdge1
9840   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9841     {
9842       std::size_t n((*it0).size()/2);
9843       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9844       std::map<int,int>::const_iterator it1;
9845       it1=mergedNodes.find(eltStart);
9846       if(it1!=mergedNodes.end())
9847         (*it0)[0]=(*it1).second;
9848       it1=mergedNodes.find(eltEnd);
9849       if(it1!=mergedNodes.end())
9850         (*it0)[2*n-1]=(*it1).second;
9851     }
9852   //
9853   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9854   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9855   // Step 2: re-order newly created nodes according to the ordering found in m2
9856   std::vector< std::vector<int> > intersectEdge2;
9857   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9858   subDiv2.clear();
9859   // Step 3: compute splitMesh1D
9860   MCAuto<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9861   MCAuto<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9862   MCAuto<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9863       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9864   MCAuto<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9865   MCAuto<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9866   // deal with cells in mesh2D that are not cut but only some of their edges are
9867   MCAuto<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCopy());
9868   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9869   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9870   MCAuto<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9871   if(!idsInDesc2DToBeRefined->empty())
9872     {
9873       DataArrayInt *out0(0),*outi0(0);
9874       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9875       MCAuto<DataArrayInt> outi0s(outi0);
9876       out0s=out0;
9877       out0s=out0s->buildUnique();
9878       out0s->sort(true);
9879     }
9880   //
9881   MCAuto<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9882   MCAuto<DataArrayDouble> baryRet1(ret1NonCol->computeCellCenterOfMass());
9883   MCAuto<DataArrayInt> elts,eltsIndex;
9884   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9885   MCAuto<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9886   MCAuto<DataArrayInt> eltsIndex3(eltsIndex2->findIdsEqual(1));
9887   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9888     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9889   MCAuto<DataArrayInt> cellsToBeModified(elts->buildUnique());
9890   MCAuto<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9891   if((DataArrayInt *)out0s)
9892     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9893   std::vector< MCAuto<MEDCouplingUMesh> > outMesh2DSplit;
9894   // OK all is ready to insert in ret2 mesh
9895   if(!untouchedCells->empty())
9896     {// the most easy part, cells in mesh2D not impacted at all
9897       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9898       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9899       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9900     }
9901   if((DataArrayInt *)out0s)
9902     {// here dealing with cells in out0s but not in cellsToBeModified
9903       MCAuto<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9904       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9905       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9906         {
9907           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9908           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9909         }
9910       int offset(ret2->getNumberOfTuples());
9911       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9912       MCAuto<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9913       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9914       int kk(0),*ret3ptr(partOfRet3->getPointer());
9915       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9916         {
9917           int faceId(std::abs(*it)-1);
9918           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9919             {
9920               int tmp(fewModifiedCells->findIdFirstEqual(*it2));
9921               if(tmp!=-1)
9922                 {
9923                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9924                     ret3ptr[2*kk]=tmp+offset;
9925                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9926                     ret3ptr[2*kk+1]=tmp+offset;
9927                 }
9928               else
9929                 {//the current edge is shared by a 2D cell that will be split just after
9930                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9931                     ret3ptr[2*kk]=-(*it2+1);
9932                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9933                     ret3ptr[2*kk+1]=-(*it2+1);
9934                 }
9935             }
9936         }
9937       m1Desc->setCoords(ret1->getCoords());
9938       ret1NonCol->setCoords(ret1->getCoords());
9939       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9940       if(!outMesh2DSplit.empty())
9941         {
9942           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9943           for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9944             (*itt)->setCoords(da);
9945         }
9946     }
9947   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9948   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9949     {
9950       MCAuto<DataArrayInt> idsNonColPerCell(elts->findIdsEqual(*it));
9951       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9952       MCAuto<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9953       MCAuto<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9954       MCAuto<DataArrayInt> partOfRet3;
9955       MCAuto<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9956       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9957       outMesh2DSplit.push_back(splitOfOneCell);
9958       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9959         ret2->pushBackSilent(*it);
9960     }
9961   //
9962   std::size_t nbOfMeshes(outMesh2DSplit.size());
9963   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9964   for(std::size_t i=0;i<nbOfMeshes;i++)
9965     tmp[i]=outMesh2DSplit[i];
9966   //
9967   ret1->getCoords()->setInfoOnComponents(compNames);
9968   MCAuto<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9969   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9970   ret3->rearrange(1);
9971   MCAuto<DataArrayInt> edgesToDealWith(ret3->findIdsStricltyNegative());
9972   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9973     {
9974       int old2DCellId(-ret3->getIJ(*it,0)-1);
9975       MCAuto<DataArrayInt> candidates(ret2->findIdsEqual(old2DCellId));
9976       ret3->setIJ(*it,0,FindRightCandidateAmong(ret2D,candidates->begin(),candidates->end(),ret1,*it%2==0?-((*it)/2+1):(*it)/2+1,eps));// div by 2 because 2 components natively in ret3
9977     }
9978   ret3->changeValue(std::numeric_limits<int>::max(),-1);
9979   ret3->rearrange(2);
9980   //
9981   splitMesh1D=ret1.retn();
9982   splitMesh2D=ret2D.retn();
9983   cellIdInMesh2D=ret2.retn();
9984   cellIdInMesh1D=ret3.retn();
9985 }
9986
9987 /**
9988  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9989  * (newly created) nodes corresponding to the edge intersections.
9990  * Output params:
9991  * @param[out] cr, crI connectivity of the resulting mesh
9992  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9993  * TODO: describe input parameters
9994  */
9995 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9996                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9997                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9998                                                          const std::vector<double>& addCoords,
9999                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
10000 {
10001   static const int SPACEDIM=2;
10002   const double *coo1(m1->getCoords()->getConstPointer());
10003   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
10004   int offset1(m1->getNumberOfNodes());
10005   const double *coo2(m2->getCoords()->getConstPointer());
10006   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
10007   int offset2(offset1+m2->getNumberOfNodes());
10008   int offset3(offset2+((int)addCoords.size())/2);
10009   MCAuto<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
10010   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10011   // Here a BBTree on 2D-cells, not on segments:
10012   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
10013   int ncell1(m1->getNumberOfCells());
10014   crI.push_back(0);
10015   for(int i=0;i<ncell1;i++)
10016     {
10017       std::vector<int> candidates2;
10018       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10019       std::map<INTERP_KERNEL::Node *,int> mapp;
10020       std::map<int,INTERP_KERNEL::Node *> mappRev;
10021       INTERP_KERNEL::QuadraticPolygon pol1;
10022       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
10023       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
10024       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
10025       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
10026       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
10027       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
10028           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
10029       //
10030       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
10031       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
10032       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10033       for(it1.first();!it1.finished();it1.next())
10034         edges1.insert(it1.current()->getPtr());
10035       //
10036       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10037       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10038       int ii=0;
10039       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10040         {
10041           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10042           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10043           // Complete mapping with elements coming from the current cell it2 in mesh2:
10044           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10045           // pol2 is the new QP in the final merged result.
10046           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10047               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10048         }
10049       ii=0;
10050       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10051         {
10052           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10053           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10054           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10055           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10056         }
10057       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10058       // by m2 but that we still want to keep in the final result.
10059       if(!edges1.empty())
10060         {
10061           try
10062           {
10063               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10064           }
10065           catch(INTERP_KERNEL::Exception& e)
10066           {
10067               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();
10068               throw INTERP_KERNEL::Exception(oss.str().c_str());
10069           }
10070         }
10071       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10072         (*it).second->decrRef();
10073     }
10074 }
10075
10076 /**
10077  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10078  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10079  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10080  * The caller is to deal with the resulting DataArrayInt.
10081  *  \throw If the coordinate array is not set.
10082  *  \throw If the nodal connectivity of the cells is not defined.
10083  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10084  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10085  *
10086  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10087  */
10088 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10089 {
10090   checkFullyDefined();
10091   if(getMeshDimension()!=1)
10092     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10093
10094   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10095   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10096   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10097   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10098   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10099   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10100   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10101   const int * dsi(_dsi->getConstPointer());
10102   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
10103   m_points=0;
10104   if (dsii->getNumberOfTuples())
10105     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10106
10107   int nc(getNumberOfCells());
10108   MCAuto<DataArrayInt> result(DataArrayInt::New());
10109   result->alloc(nc,1);
10110
10111   // set of edges not used so far
10112   std::set<int> edgeSet;
10113   for (int i=0; i<nc; edgeSet.insert(i), i++);
10114
10115   int startSeg=0;
10116   int newIdx=0;
10117   // while we have points with only one neighbor segments
10118   do
10119     {
10120       std::list<int> linePiece;
10121       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10122       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10123         {
10124           // Fill the list forward (resp. backward) from the start segment:
10125           int activeSeg = startSeg;
10126           int prevPointId = -20;
10127           int ptId;
10128           while (!edgeSet.empty())
10129             {
10130               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10131                 {
10132                   if (direction==0)
10133                     linePiece.push_back(activeSeg);
10134                   else
10135                     linePiece.push_front(activeSeg);
10136                   edgeSet.erase(activeSeg);
10137                 }
10138
10139               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10140               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10141               if (dsi[ptId] == 1) // hitting the end of the line
10142                 break;
10143               prevPointId = ptId;
10144               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10145               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10146             }
10147         }
10148       // Done, save final piece into DA:
10149       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10150       newIdx += linePiece.size();
10151
10152       // identify next valid start segment (one which is not consumed)
10153       if(!edgeSet.empty())
10154         startSeg = *(edgeSet.begin());
10155     }
10156   while (!edgeSet.empty());
10157   return result.retn();
10158 }
10159
10160 /// @cond INTERNAL
10161
10162 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10163 {
10164   MCAuto<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10165   std::map<MCAuto<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10166   if(it==m.end())
10167     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10168   int v((*it).second);
10169   if(v==forbVal0 || v==forbVal1)
10170     return ;
10171   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10172     isect.push_back(v);
10173 }
10174
10175 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10176 {
10177   int sz(c.size());
10178   if(sz<=1)
10179     return false;
10180   bool presenceOfOn(false);
10181   for(int i=0;i<sz;i++)
10182     {
10183       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10184       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10185         continue ;
10186       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10187       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10188     }
10189   return presenceOfOn;
10190 }
10191
10192 /// @endcond
10193
10194 /**
10195  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10196  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10197  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10198  * a minimal creation of new nodes is wanted.
10199  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10200  * nodes if a SEG3 is split without information of middle.
10201  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10202  * avoid to have a non conform mesh.
10203  *
10204  * \return int - the number of new nodes created (in most of cases 0).
10205  * 
10206  * \throw If \a this is not coherent.
10207  * \throw If \a this has not spaceDim equal to 2.
10208  * \throw If \a this has not meshDim equal to 2.
10209  * \throw If some subcells needed to be split are orphan.
10210  * \sa MEDCouplingUMesh::conformize2D
10211  */
10212 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10213 {
10214   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10215     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10216   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10217   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10218     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10219   if(midOpt==0 && midOptI==0)
10220     {
10221       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10222       return 0;
10223     }
10224   else if(midOpt!=0 && midOptI!=0)
10225     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10226   else
10227     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10228 }
10229
10230 /*!
10231  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10232  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10233  * 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
10234  * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges are both linear (INTERP_KERNEL::NORM_SEG2).
10235  * In the other cases new nodes can be created. If any are created, they will be appended at the end of the coordinates object before the invokation of this method.
10236  * 
10237  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10238  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10239  *
10240  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10241  * This method expects that all nodes in \a this are not closer than \a eps.
10242  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10243  * 
10244  * \param [in] eps the relative error to detect merged edges.
10245  * \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
10246  *                           that the user is expected to deal with.
10247  *
10248  * \throw If \a this is not coherent.
10249  * \throw If \a this has not spaceDim equal to 2.
10250  * \throw If \a this has not meshDim equal to 2.
10251  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10252  */
10253 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10254 {
10255   static const int SPACEDIM=2;
10256   checkConsistencyLight();
10257   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10258     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10259   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10260   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10261   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10262   MCAuto<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10263   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10264   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10265   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10266   std::vector<double> addCoo;
10267   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10268   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10269   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10270   for(int i=0;i<nDescCell;i++)
10271     {
10272       std::vector<int> candidates;
10273       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10274       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10275         if(*it>i)
10276           {
10277             std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10278             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10279                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10280             INTERP_KERNEL::MergePoints merge;
10281             INTERP_KERNEL::QuadraticPolygon c1,c2;
10282             e1->intersectWith(e2,merge,c1,c2);
10283             e1->decrRef(); e2->decrRef();
10284             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10285               overlapEdge[i].push_back(*it);
10286             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10287               overlapEdge[*it].push_back(i);
10288           }
10289     }
10290   // splitting done. sort intersect point in intersectEdge.
10291   std::vector< std::vector<int> > middle(nDescCell);
10292   int nbOf2DCellsToBeSplit(0);
10293   bool middleNeedsToBeUsed(false);
10294   std::vector<bool> cells2DToTreat(nDescCell,false);
10295   for(int i=0;i<nDescCell;i++)
10296     {
10297       std::vector<int>& isect(intersectEdge[i]);
10298       int sz((int)isect.size());
10299       if(sz>1)
10300         {
10301           std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10302           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10303           e->sortSubNodesAbs(coords,isect);
10304           e->decrRef();
10305         }
10306       if(sz!=0)
10307         {
10308           int idx0(rdi[i]),idx1(rdi[i+1]);
10309           if(idx1-idx0!=1)
10310             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10311           if(!cells2DToTreat[rd[idx0]])
10312             {
10313               cells2DToTreat[rd[idx0]]=true;
10314               nbOf2DCellsToBeSplit++;
10315             }
10316           // try to reuse at most eventual 'middle' of SEG3
10317           std::vector<int>& mid(middle[i]);
10318           mid.resize(sz+1,-1);
10319           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10320             {
10321               middleNeedsToBeUsed=true;
10322               const std::vector<int>& candidates(overlapEdge[i]);
10323               std::vector<int> trueCandidates;
10324               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10325                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10326                   trueCandidates.push_back(*itc);
10327               int stNode(c[ci[i]+1]),endNode(isect[0]);
10328               for(int j=0;j<sz+1;j++)
10329                 {
10330                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10331                     {
10332                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10333                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10334                         { mid[j]=*itc; break; }
10335                     }
10336                   stNode=endNode;
10337                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10338                 }
10339             }
10340         }
10341     }
10342   MCAuto<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10343   if(nbOf2DCellsToBeSplit==0)
10344     return ret.retn();
10345   //
10346   int *retPtr(ret->getPointer());
10347   for(int i=0;i<nCell;i++)
10348     if(cells2DToTreat[i])
10349       *retPtr++=i;
10350   //
10351   MCAuto<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10352   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10353   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10354   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10355   if(middleNeedsToBeUsed)
10356     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10357   MCAuto<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10358   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10359   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.
10360   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10361   {
10362     bool areNodesMerged; int newNbOfNodes;
10363     if(nbOfNodesCreated!=0)
10364       MCAuto<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10365   }
10366   return ret.retn();
10367 }
10368
10369 /*!
10370  * This non const method works on 2D mesh. This method scans every cell in \a this and look if each edge constituting this cell is not mergeable with neighbors edges of that cell.
10371  * If yes, the cell is "repaired" to minimize at most its number of edges. So this method do not change the overall shape of cells in \a this (with eps precision).
10372  * This method do not take care of shared edges between cells, so this method can lead to a non conform mesh (\a this). If a conform mesh is required you're expected
10373  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10374  * This method works on any 2D geometric types of cell (even static one). If a cell is touched its type becomes dynamic automaticaly. For 2D "repaired" quadratic cells
10375  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10376  *
10377  * If the returned array is empty it means that nothing has changed in \a this (as if it were a const method). If the array is not empty the connectivity of \a this is modified
10378  * using new instance, idem for coordinates.
10379  *
10380  * If \a this is constituted by only linear 2D cells, this method is close to the computation of the convex hull of each cells in \a this.
10381  * 
10382  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10383  *
10384  * \throw If \a this is not coherent.
10385  * \throw If \a this has not spaceDim equal to 2.
10386  * \throw If \a this has not meshDim equal to 2.
10387  * 
10388  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10389  */
10390 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10391 {
10392   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10393   checkConsistencyLight();
10394   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10395     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10396   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10397   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10398   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10399   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10400   MCAuto<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10401   MCAuto<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10402   const double *coords(_coords->begin());
10403   int *newciptr(newci->getPointer());
10404   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10405     {
10406       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10407         ret->pushBackSilent(i);
10408       newciptr[1]=newc->getNumberOfTuples();
10409     }
10410   //
10411   if(ret->empty())
10412     return ret.retn();
10413   if(!appendedCoords->empty())
10414     {
10415       appendedCoords->rearrange(2);
10416       MCAuto<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10417       //non const part
10418       setCoords(newCoords);
10419     }
10420   //non const part
10421   setConnectivity(newc,newci,true);
10422   return ret.retn();
10423 }
10424
10425 /*!
10426  * \param [out] intersectEdge1 - for each cell in \a m1Desc returns the result of the split. The result is given using pair of int given resp start and stop.
10427  *                               So for all edge \a i in \a m1Desc \a  intersectEdge1[i] is of length 2*n where n is the number of sub edges.
10428  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10429  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10430  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10431  * \param [out] addCoo - nodes to be append at the end
10432  * \param [out] mergedNodes - gives all pair of nodes of \a m2Desc that have same location than some nodes in \a m1Desc. key is id in \a m2Desc offseted and value is id in \a m1Desc.
10433  */
10434 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10435                                          std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2, std::vector<double>& addCoo, std::map<int,int>& mergedNodes)
10436 {
10437   static const int SPACEDIM=2;
10438   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10439   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10440   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10441   // Build BB tree of all edges in the tool mesh (second mesh)
10442   MCAuto<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10443   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10444   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10445   intersectEdge1.resize(nDescCell1);
10446   colinear2.resize(nDescCell2);
10447   subDiv2.resize(nDescCell2);
10448   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10449
10450   std::vector<int> candidates1(1);
10451   int offset1(m1Desc->getNumberOfNodes());
10452   int offset2(offset1+m2Desc->getNumberOfNodes());
10453   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10454     {
10455       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10456       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10457       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10458         {
10459           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10460           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10461           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10462           candidates1[0]=i;
10463           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10464           // 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
10465           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10466           std::set<INTERP_KERNEL::Node *> nodes;
10467           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10468           std::size_t szz(nodes.size());
10469           std::vector< MCAuto<INTERP_KERNEL::Node> > nodesSafe(szz);
10470           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10471           for(std::size_t iii=0;iii<szz;iii++,itt++)
10472             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10473           // end of protection
10474           // Performs egde cutting:
10475           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10476           delete pol2;
10477           delete pol1;
10478         }
10479       else
10480         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10481         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10482     }
10483 }
10484
10485 /*!
10486  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10487  * It builds the descending connectivity of the two meshes, and then using a binary tree
10488  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10489  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10490  */
10491 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10492                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10493                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10494                                                    std::vector<double>& addCoo,
10495                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10496 {
10497   // Build desc connectivity
10498   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10499   desc2=DataArrayInt::New();
10500   descIndx2=DataArrayInt::New();
10501   revDesc2=DataArrayInt::New();
10502   revDescIndx2=DataArrayInt::New();
10503   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10504   MCAuto<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10505   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10506   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10507   MCAuto<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10508   std::map<int,int> notUsedMap;
10509   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10510   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10511   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10512 }
10513
10514 /*!
10515  * This method performs the 2nd step of Partition of 2D mesh.
10516  * This method has 4 inputs :
10517  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10518  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10519  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10520  * 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'
10521  * Nodes end up lying consecutively on a cutted edge.
10522  * \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.
10523  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10524  * \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.
10525  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10526  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10527  */
10528 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10529                                            const std::vector<double>& addCoo,
10530                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10531 {
10532   int offset1=m1->getNumberOfNodes();
10533   int ncell=m2->getNumberOfCells();
10534   const int *c=m2->getNodalConnectivity()->getConstPointer();
10535   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10536   const double *coo=m2->getCoords()->getConstPointer();
10537   const double *cooBis=m1->getCoords()->getConstPointer();
10538   int offset2=offset1+m2->getNumberOfNodes();
10539   intersectEdge.resize(ncell);
10540   for(int i=0;i<ncell;i++,cI++)
10541     {
10542       const std::vector<int>& divs=subDiv[i];
10543       int nnode=cI[1]-cI[0]-1;
10544       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10545       std::map<INTERP_KERNEL::Node *, int> mapp22;
10546       for(int j=0;j<nnode;j++)
10547         {
10548           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10549           int nnid=c[(*cI)+j+1];
10550           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10551           mapp22[nn]=nnid+offset1;
10552         }
10553       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10554       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10555         ((*it).second.first)->decrRef();
10556       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10557       std::map<INTERP_KERNEL::Node *,int> mapp3;
10558       for(std::size_t j=0;j<divs.size();j++)
10559         {
10560           int id=divs[j];
10561           INTERP_KERNEL::Node *tmp=0;
10562           if(id<offset1)
10563             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10564           else if(id<offset2)
10565             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10566           else
10567             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10568           addNodes[j]=tmp;
10569           mapp3[tmp]=id;
10570         }
10571       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10572       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10573         (*it)->decrRef();
10574       e->decrRef();
10575     }
10576 }
10577
10578 /*!
10579  * 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).
10580  * 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
10581  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10582  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10583  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10584  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10585  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10586  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10587  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10588  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10589  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10590  * \param [out] cut3DSuf input/output param.
10591  */
10592 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10593                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10594                                                    const int *desc, const int *descIndx, 
10595                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10596 {
10597   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10598   int nbOf3DSurfCell=(int)cut3DSurf.size();
10599   for(int i=0;i<nbOf3DSurfCell;i++)
10600     {
10601       std::vector<int> res;
10602       int offset=descIndx[i];
10603       int nbOfSeg=descIndx[i+1]-offset;
10604       for(int j=0;j<nbOfSeg;j++)
10605         {
10606           int edgeId=desc[offset+j];
10607           int status=cut3DCurve[edgeId];
10608           if(status!=-2)
10609             {
10610               if(status>-1)
10611                 res.push_back(status);
10612               else
10613                 {
10614                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10615                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10616                 }
10617             }
10618         }
10619       switch(res.size())
10620       {
10621         case 2:
10622           {
10623             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10624             break;
10625           }
10626         case 1:
10627         case 0:
10628           {
10629             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10630             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10631             if(res.size()==2)
10632               {
10633                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10634               }
10635             else
10636               {
10637                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10638               }
10639             break;
10640           }
10641         default:
10642           {// case when plane is on a multi colinear edge of a polyhedron
10643             if((int)res.size()==2*nbOfSeg)
10644               {
10645                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10646               }
10647             else
10648               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10649           }
10650       }
10651     }
10652 }
10653
10654 /*!
10655  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10656  * 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).
10657  * 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
10658  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10659  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10660  * \param desc is the descending connectivity 3D->3DSurf
10661  * \param descIndx is the descending connectivity index 3D->3DSurf
10662  */
10663 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10664                                                   const int *desc, const int *descIndx,
10665                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10666 {
10667   checkFullyDefined();
10668   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10669     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10670   const int *nodal3D=_nodal_connec->getConstPointer();
10671   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10672   int nbOfCells=getNumberOfCells();
10673   for(int i=0;i<nbOfCells;i++)
10674     {
10675       std::map<int, std::set<int> > m;
10676       int offset=descIndx[i];
10677       int nbOfFaces=descIndx[i+1]-offset;
10678       int start=-1;
10679       int end=-1;
10680       for(int j=0;j<nbOfFaces;j++)
10681         {
10682           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10683           if(p.first!=-1 && p.second!=-1)
10684             {
10685               if(p.first!=-2)
10686                 {
10687                   start=p.first; end=p.second;
10688                   m[p.first].insert(p.second);
10689                   m[p.second].insert(p.first);
10690                 }
10691               else
10692                 {
10693                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10694                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10695                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10696                   INTERP_KERNEL::NormalizedCellType cmsId;
10697                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10698                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10699                   for(unsigned k=0;k<nbOfNodesSon;k++)
10700                     {
10701                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10702                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10703                     }
10704                 }
10705             }
10706         }
10707       if(m.empty())
10708         continue;
10709       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10710       int prev=end;
10711       while(end!=start)
10712         {
10713           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10714           const std::set<int>& s=(*it).second;
10715           std::set<int> s2; s2.insert(prev);
10716           std::set<int> s3;
10717           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10718           if(s3.size()==1)
10719             {
10720               int val=*s3.begin();
10721               conn.push_back(start);
10722               prev=start;
10723               start=val;
10724             }
10725           else
10726             start=end;
10727         }
10728       conn.push_back(end);
10729       if(conn.size()>3)
10730         {
10731           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10732           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10733           cellIds->pushBackSilent(i);
10734         }
10735     }
10736 }
10737
10738 /*!
10739  * 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
10740  * 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
10741  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10742  * 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
10743  * 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.
10744  * 
10745  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10746  */
10747 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10748 {
10749   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10750   if(sz>=4)
10751     {
10752       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10753       if(cm.getDimension()==2)
10754         {
10755           const int *node=nodalConnBg+1;
10756           int startNode=*node++;
10757           double refX=coords[2*startNode];
10758           for(;node!=nodalConnEnd;node++)
10759             {
10760               if(coords[2*(*node)]<refX)
10761                 {
10762                   startNode=*node;
10763                   refX=coords[2*startNode];
10764                 }
10765             }
10766           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10767           refX=1e300;
10768           double tmp1;
10769           double tmp2[2];
10770           double angle0=-M_PI/2;
10771           //
10772           int nextNode=-1;
10773           int prevNode=-1;
10774           double resRef;
10775           double angleNext=0.;
10776           while(nextNode!=startNode)
10777             {
10778               nextNode=-1;
10779               resRef=1e300;
10780               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10781                 {
10782                   if(*node!=tmpOut.back() && *node!=prevNode)
10783                     {
10784                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10785                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10786                       double res;
10787                       if(angleM<=angle0)
10788                         res=angle0-angleM;
10789                       else
10790                         res=angle0-angleM+2.*M_PI;
10791                       if(res<resRef)
10792                         {
10793                           nextNode=*node;
10794                           resRef=res;
10795                           angleNext=angleM;
10796                         }
10797                     }
10798                 }
10799               if(nextNode!=startNode)
10800                 {
10801                   angle0=angleNext-M_PI;
10802                   if(angle0<-M_PI)
10803                     angle0+=2*M_PI;
10804                   prevNode=tmpOut.back();
10805                   tmpOut.push_back(nextNode);
10806                 }
10807             }
10808           std::vector<int> tmp3(2*(sz-1));
10809           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10810           std::copy(nodalConnBg+1,nodalConnEnd,it);
10811           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10812             {
10813               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10814               return false;
10815             }
10816           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10817             {
10818               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10819               return false;
10820             }
10821           else
10822             {
10823               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10824               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10825               return true;
10826             }
10827         }
10828       else
10829         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10830     }
10831   else
10832     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10833 }
10834
10835 /*!
10836  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10837  * 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.
10838  * 
10839  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10840  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10841  * \param [in,out] arr array in which the remove operation will be done.
10842  * \param [in,out] arrIndx array in the remove operation will modify
10843  * \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])
10844  * \return true if \b arr and \b arrIndx have been modified, false if not.
10845  */
10846 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10847 {
10848   if(!arrIndx || !arr)
10849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10850   if(offsetForRemoval<0)
10851     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10852   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10853   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10854   int *arrIPtr=arrIndx->getPointer();
10855   *arrIPtr++=0;
10856   int previousArrI=0;
10857   const int *arrPtr=arr->getConstPointer();
10858   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10859   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10860     {
10861       if(*arrIPtr-previousArrI>offsetForRemoval)
10862         {
10863           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10864             {
10865               if(s.find(*work)==s.end())
10866                 arrOut.push_back(*work);
10867             }
10868         }
10869       previousArrI=*arrIPtr;
10870       *arrIPtr=(int)arrOut.size();
10871     }
10872   if(arr->getNumberOfTuples()==(int)arrOut.size())
10873     return false;
10874   arr->alloc((int)arrOut.size(),1);
10875   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10876   return true;
10877 }
10878
10879 /*!
10880  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10881  * (\ref numbering-indirect).
10882  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10883  * The selection of extraction is done standardly in new2old format.
10884  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10885  *
10886  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10887  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10888  * \param [in] arrIn arr origin array from which the extraction will be done.
10889  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10890  * \param [out] arrOut the resulting array
10891  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10892  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
10893  */
10894 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10895                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10896 {
10897   if(!arrIn || !arrIndxIn)
10898     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10899   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10900   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10901     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10902   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10903   const int *arrInPtr=arrIn->getConstPointer();
10904   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10905   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10906   if(nbOfGrps<0)
10907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10908   int maxSizeOfArr=arrIn->getNumberOfTuples();
10909   MCAuto<DataArrayInt> arro=DataArrayInt::New();
10910   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
10911   arrIo->alloc((int)(sz+1),1);
10912   const int *idsIt=idsOfSelectBg;
10913   int *work=arrIo->getPointer();
10914   *work++=0;
10915   int lgth=0;
10916   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10917     {
10918       if(*idsIt>=0 && *idsIt<nbOfGrps)
10919         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10920       else
10921         {
10922           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10923           throw INTERP_KERNEL::Exception(oss.str().c_str());
10924         }
10925       if(lgth>=work[-1])
10926         *work=lgth;
10927       else
10928         {
10929           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10930           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10931           throw INTERP_KERNEL::Exception(oss.str().c_str());
10932         }
10933     }
10934   arro->alloc(lgth,1);
10935   work=arro->getPointer();
10936   idsIt=idsOfSelectBg;
10937   for(std::size_t i=0;i<sz;i++,idsIt++)
10938     {
10939       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10940         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10941       else
10942         {
10943           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10944           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10945           throw INTERP_KERNEL::Exception(oss.str().c_str());
10946         }
10947     }
10948   arrOut=arro.retn();
10949   arrIndexOut=arrIo.retn();
10950 }
10951
10952 /*!
10953  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10954  * (\ref numbering-indirect).
10955  * 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 ).
10956  * The selection of extraction is done standardly in new2old format.
10957  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10958  *
10959  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10960  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10961  * \param [in] idsOfSelectStep
10962  * \param [in] arrIn arr origin array from which the extraction will be done.
10963  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10964  * \param [out] arrOut the resulting array
10965  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10966  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10967  */
10968 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10969                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10970 {
10971   if(!arrIn || !arrIndxIn)
10972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
10973   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10974   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10975     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
10976   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
10977   const int *arrInPtr=arrIn->getConstPointer();
10978   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10979   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10980   if(nbOfGrps<0)
10981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10982   int maxSizeOfArr=arrIn->getNumberOfTuples();
10983   MCAuto<DataArrayInt> arro=DataArrayInt::New();
10984   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
10985   arrIo->alloc((int)(sz+1),1);
10986   int idsIt=idsOfSelectStart;
10987   int *work=arrIo->getPointer();
10988   *work++=0;
10989   int lgth=0;
10990   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10991     {
10992       if(idsIt>=0 && idsIt<nbOfGrps)
10993         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10994       else
10995         {
10996           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10997           throw INTERP_KERNEL::Exception(oss.str().c_str());
10998         }
10999       if(lgth>=work[-1])
11000         *work=lgth;
11001       else
11002         {
11003           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
11004           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
11005           throw INTERP_KERNEL::Exception(oss.str().c_str());
11006         }
11007     }
11008   arro->alloc(lgth,1);
11009   work=arro->getPointer();
11010   idsIt=idsOfSelectStart;
11011   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
11012     {
11013       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
11014         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
11015       else
11016         {
11017           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
11018           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11019           throw INTERP_KERNEL::Exception(oss.str().c_str());
11020         }
11021     }
11022   arrOut=arro.retn();
11023   arrIndexOut=arrIo.retn();
11024 }
11025
11026 /*!
11027  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11028  * 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
11029  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11030  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11031  *
11032  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11033  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11034  * \param [in] arrIn arr origin array from which the extraction will be done.
11035  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11036  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11037  * \param [in] srcArrIndex index array of \b srcArr
11038  * \param [out] arrOut the resulting array
11039  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11040  * 
11041  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11042  */
11043 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11044                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11045                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11046 {
11047   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11048     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11049   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11050   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11051   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11052   std::vector<bool> v(nbOfTuples,true);
11053   int offset=0;
11054   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11055   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11056   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11057     {
11058       if(*it>=0 && *it<nbOfTuples)
11059         {
11060           v[*it]=false;
11061           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11062         }
11063       else
11064         {
11065           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11066           throw INTERP_KERNEL::Exception(oss.str().c_str());
11067         }
11068     }
11069   srcArrIndexPtr=srcArrIndex->getConstPointer();
11070   arrIo->alloc(nbOfTuples+1,1);
11071   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11072   const int *arrInPtr=arrIn->getConstPointer();
11073   const int *srcArrPtr=srcArr->getConstPointer();
11074   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11075   int *arroPtr=arro->getPointer();
11076   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11077     {
11078       if(v[ii])
11079         {
11080           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11081           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11082         }
11083       else
11084         {
11085           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11086           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11087           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11088         }
11089     }
11090   arrOut=arro.retn();
11091   arrIndexOut=arrIo.retn();
11092 }
11093
11094 /*!
11095  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11096  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11097  *
11098  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11099  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11100  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11101  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11102  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11103  * \param [in] srcArrIndex index array of \b srcArr
11104  * 
11105  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11106  */
11107 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11108                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11109 {
11110   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11112   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11113   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11114   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11115   int *arrInOutPtr=arrInOut->getPointer();
11116   const int *srcArrPtr=srcArr->getConstPointer();
11117   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11118     {
11119       if(*it>=0 && *it<nbOfTuples)
11120         {
11121           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11122             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11123           else
11124             {
11125               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] !";
11126               throw INTERP_KERNEL::Exception(oss.str().c_str());
11127             }
11128         }
11129       else
11130         {
11131           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11132           throw INTERP_KERNEL::Exception(oss.str().c_str());
11133         }
11134     }
11135 }
11136
11137 /*!
11138  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11139  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11140  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
11141  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11142  * A negative value in \b arrIn means that it is ignored.
11143  * 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.
11144  * 
11145  * \param [in] arrIn arr origin array from which the extraction will be done.
11146  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11147  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11148  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11149  */
11150 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11151 {
11152   int seed=0,nbOfDepthPeelingPerformed=0;
11153   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11154 }
11155
11156 /*!
11157  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11158  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11159  * 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]].
11160  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11161  * A negative value in \b arrIn means that it is ignored.
11162  * 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.
11163  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11164  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11165  * \param [in] arrIn arr origin array from which the extraction will be done.
11166  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11167  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11168  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11169  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11170  * \sa MEDCouplingUMesh::partitionBySpreadZone
11171  */
11172 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11173 {
11174   nbOfDepthPeelingPerformed=0;
11175   if(!arrIndxIn)
11176     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11177   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11178   if(nbOfTuples<=0)
11179     {
11180       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11181       return ret;
11182     }
11183   //
11184   std::vector<bool> fetched(nbOfTuples,false);
11185   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11186 }
11187
11188 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11189 {
11190   nbOfDepthPeelingPerformed=0;
11191   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11192     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11193   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11194   std::vector<bool> fetched2(nbOfTuples,false);
11195   int i=0;
11196   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11197     {
11198       if(*seedElt>=0 && *seedElt<nbOfTuples)
11199         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11200       else
11201         { 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()); }
11202     }
11203   const int *arrInPtr=arrIn->getConstPointer();
11204   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11205   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11206   std::vector<int> idsToFetch1(seedBg,seedEnd);
11207   std::vector<int> idsToFetch2;
11208   std::vector<int> *idsToFetch=&idsToFetch1;
11209   std::vector<int> *idsToFetchOther=&idsToFetch2;
11210   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11211     {
11212       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11213         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11214           if(!fetched[*it2])
11215             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11216       std::swap(idsToFetch,idsToFetchOther);
11217       idsToFetchOther->clear();
11218       nbOfDepthPeelingPerformed++;
11219     }
11220   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11221   i=0;
11222   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11223   int *retPtr=ret->getPointer();
11224   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11225     if(*it)
11226       *retPtr++=i;
11227   return ret.retn();
11228 }
11229
11230 /*!
11231  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11232  * 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
11233  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11234  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11235  *
11236  * \param [in] start begin of set of ids of the input extraction (included)
11237  * \param [in] end end of set of ids of the input extraction (excluded)
11238  * \param [in] step step of the set of ids in range mode.
11239  * \param [in] arrIn arr origin array from which the extraction will be done.
11240  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11241  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11242  * \param [in] srcArrIndex index array of \b srcArr
11243  * \param [out] arrOut the resulting array
11244  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11245  * 
11246  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11247  */
11248 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11249                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11250                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11251 {
11252   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11253     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
11254   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11255   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11256   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11257   int offset=0;
11258   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11259   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11260   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
11261   int it=start;
11262   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11263     {
11264       if(it>=0 && it<nbOfTuples)
11265         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11266       else
11267         {
11268           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11269           throw INTERP_KERNEL::Exception(oss.str().c_str());
11270         }
11271     }
11272   srcArrIndexPtr=srcArrIndex->getConstPointer();
11273   arrIo->alloc(nbOfTuples+1,1);
11274   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11275   const int *arrInPtr=arrIn->getConstPointer();
11276   const int *srcArrPtr=srcArr->getConstPointer();
11277   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11278   int *arroPtr=arro->getPointer();
11279   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11280     {
11281       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11282       if(pos<0)
11283         {
11284           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11285           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11286         }
11287       else
11288         {
11289           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11290           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11291         }
11292     }
11293   arrOut=arro.retn();
11294   arrIndexOut=arrIo.retn();
11295 }
11296
11297 /*!
11298  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11299  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11300  *
11301  * \param [in] start begin of set of ids of the input extraction (included)
11302  * \param [in] end end of set of ids of the input extraction (excluded)
11303  * \param [in] step step of the set of ids in range mode.
11304  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11305  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11306  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11307  * \param [in] srcArrIndex index array of \b srcArr
11308  * 
11309  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11310  */
11311 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11312                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11313 {
11314   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11315     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
11316   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11317   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11318   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11319   int *arrInOutPtr=arrInOut->getPointer();
11320   const int *srcArrPtr=srcArr->getConstPointer();
11321   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
11322   int it=start;
11323   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11324     {
11325       if(it>=0 && it<nbOfTuples)
11326         {
11327           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11328             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11329           else
11330             {
11331               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11332               throw INTERP_KERNEL::Exception(oss.str().c_str());
11333             }
11334         }
11335       else
11336         {
11337           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11338           throw INTERP_KERNEL::Exception(oss.str().c_str());
11339         }
11340     }
11341 }
11342
11343 /*!
11344  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11345  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11346  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11347  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11348  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11349  * 
11350  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11351  */
11352 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11353 {
11354   checkFullyDefined();
11355   int mdim=getMeshDimension();
11356   int spaceDim=getSpaceDimension();
11357   if(mdim!=spaceDim)
11358     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11359   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11360   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11361   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
11362   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11363   ret->setCoords(getCoords());
11364   ret->allocateCells((int)partition.size());
11365   //
11366   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11367     {
11368       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11369       MCAuto<DataArrayInt> cell;
11370       switch(mdim)
11371       {
11372         case 2:
11373           cell=tmp->buildUnionOf2DMesh();
11374           break;
11375         case 3:
11376           cell=tmp->buildUnionOf3DMesh();
11377           break;
11378         default:
11379           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11380       }
11381
11382       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11383     }
11384   //
11385   ret->finishInsertingCells();
11386   return ret.retn();
11387 }
11388
11389 /*!
11390  * This method partitions \b this into contiguous zone.
11391  * This method only needs a well defined connectivity. Coordinates are not considered here.
11392  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11393  */
11394 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11395 {
11396   int nbOfCellsCur=getNumberOfCells();
11397   std::vector<DataArrayInt *> ret;
11398   if(nbOfCellsCur<=0)
11399     return ret;
11400   DataArrayInt *neigh=0,*neighI=0;
11401   computeNeighborsOfCells(neigh,neighI);
11402   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11403   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11404   std::vector< MCAuto<DataArrayInt> > ret2;
11405   int seed=0;
11406   while(seed<nbOfCellsCur)
11407     {
11408       int nbOfPeelPerformed=0;
11409       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11410       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11411     }
11412   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11413     ret.push_back((*it).retn());
11414   return ret;
11415 }
11416
11417 /*!
11418  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11419  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11420  *
11421  * \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.
11422  * \return a newly allocated DataArrayInt to be managed by the caller.
11423  * \throw In case of \a code has not the right format (typically of size 3*n)
11424  */
11425 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11426 {
11427   MCAuto<DataArrayInt> ret=DataArrayInt::New();
11428   std::size_t nb=code.size()/3;
11429   if(code.size()%3!=0)
11430     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11431   ret->alloc((int)nb,2);
11432   int *retPtr=ret->getPointer();
11433   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11434     {
11435       retPtr[0]=code[3*i+2];
11436       retPtr[1]=code[3*i+2]+code[3*i+1];
11437     }
11438   return ret.retn();
11439 }
11440
11441 /*!
11442  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11443  * All cells in \a this are expected to be linear 3D cells.
11444  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11445  * It leads to an increase to number of cells.
11446  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11447  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11448  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11449  *
11450  * \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.
11451  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11452  * \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. 
11453  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11454  *          an id of old cell producing it. The caller is to delete this array using
11455  *         decrRef() as it is no more needed.
11456  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11457  *
11458  * \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
11459  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11460  * 
11461  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11462  * \throw If \a this is not fully constituted with linear 3D cells.
11463  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11464  */
11465 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11466 {
11467   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11468   checkConnectivityFullyDefined();
11469   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11470     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11471   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11472   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11473   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11474   int *retPt(ret->getPointer());
11475   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11476   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11477   const int *oldc(_nodal_connec->begin());
11478   const int *oldci(_nodal_connec_index->begin());
11479   const double *coords(_coords->begin());
11480   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11481     {
11482       std::vector<int> a; std::vector<double> b;
11483       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11484       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11485       const int *aa(&a[0]);
11486       if(!b.empty())
11487         {
11488           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11489             if(*it<0)
11490               *it=(-(*(it))-1+nbNodes);
11491           addPts->insertAtTheEnd(b.begin(),b.end());
11492           nbNodes+=(int)b.size()/3;
11493         }
11494       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11495         newConn->insertAtTheEnd(aa,aa+4);
11496     }
11497   if(!addPts->empty())
11498     {
11499       addPts->rearrange(3);
11500       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11501       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11502       ret0->setCoords(addPts);
11503     }
11504   else
11505     {
11506       nbOfAdditionalPoints=0;
11507       ret0->setCoords(getCoords());
11508     }
11509   ret0->setNodalConnectivity(newConn);
11510   //
11511   ret->computeOffsetsFull();
11512   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11513   return ret0.retn();
11514 }
11515
11516 /*!
11517  * 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). 
11518  *
11519  * \sa MEDCouplingUMesh::split2DCells
11520  */
11521 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11522 {
11523   checkConnectivityFullyDefined();
11524   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+subNodesInSeg->getNumberOfTuples());
11525   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11526   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11527   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11528   int prevPosOfCi(ciPtr[0]);
11529   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11530     {
11531       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11532       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11533       for(int j=0;j<sz;j++)
11534         {
11535           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11536           for(int k=0;k<sz2;k++)
11537             *cPtr++=subPtr[offset2+k];
11538           if(j!=sz-1)
11539             *cPtr++=oldConn[prevPosOfCi+j+2];
11540           deltaSz+=sz2;
11541         }
11542       prevPosOfCi=ciPtr[1];
11543       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11544     }
11545   if(c->end()!=cPtr)
11546     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11547   _nodal_connec->decrRef();
11548   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11549 }
11550
11551 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11552 {
11553   if(id!=-1)
11554     return id;
11555   else
11556     {
11557       int ret(nodesCnter++);
11558       double newPt[2];
11559       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11560       addCoo.insertAtTheEnd(newPt,newPt+2);
11561       return ret;
11562     }
11563 }
11564
11565 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11566 {
11567   if(id!=-1)
11568     return id;
11569   else
11570     {
11571       int ret(nodesCnter++);
11572       double newPt[2];
11573       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11574       addCoo.insertAtTheEnd(newPt,newPt+2);
11575       return ret;
11576     }
11577 }
11578
11579
11580 /// @cond INTERNAL
11581
11582 void EnterTheResultOf2DCellFirst(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11583 {
11584   int tmp[3];
11585   int trueStart(start>=0?start:nbOfEdges+start);
11586   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11587   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11588   if(linOrArc)
11589     {
11590       if(stp-start>1)
11591         {
11592           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11593           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11594           middles.push_back(tmp3+offset);
11595         }
11596       else
11597         middles.push_back(connBg[trueStart+nbOfEdges]);
11598     }
11599 }
11600
11601 void EnterTheResultOf2DCellMiddle(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11602 {
11603   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11604   newConnOfCell->pushBackSilent(tmpEnd);
11605   if(linOrArc)
11606     {
11607       if(stp-start>1)
11608         {
11609           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11610           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11611           middles.push_back(tmp3+offset);
11612         }
11613       else
11614         middles.push_back(connBg[start+nbOfEdges]);
11615     }
11616 }
11617
11618 void EnterTheResultOf2DCellEnd(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11619 {
11620   // only the quadratic point to deal with:
11621   if(linOrArc)
11622     {
11623       if(stp-start>1)
11624         {
11625           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11626           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11627           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11628           middles.push_back(tmp3+offset);
11629         }
11630       else
11631         middles.push_back(connBg[start+nbOfEdges]);
11632     }
11633 }
11634
11635 /// @endcond
11636
11637 /*!
11638  * Returns true if a colinearization has been found in the given cell. If false is returned the content pushed in \a newConnOfCell is equal to [ \a connBg , \a connEnd ) .
11639  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11640  */
11641 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11642 {
11643   std::size_t sz(std::distance(connBg,connEnd));
11644   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11645     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11646   sz--;
11647   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11648   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11649   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11650   unsigned nbOfHit(0); // number of fusions operated
11651   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11652   const unsigned int maxNbOfHit = cm.isQuadratic() ? nbs-2 : nbs-3;  // a quad cell is authorized to end up with only two edges, a linear one has to keep 3 at least
11653   INTERP_KERNEL::NormalizedCellType typeOfSon;
11654   std::vector<int> middles;
11655   bool ret(false);
11656   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11657     {
11658       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11659       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
11660       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11661       posEndElt = posBaseElt+1;
11662
11663       // Look backward first: are the final edges of the cells colinear with the first ones?
11664       // This initializes posBaseElt.
11665       if(nbOfTurn==0)
11666         {
11667           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11668             {
11669               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11670               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11671               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11672               bool isColinear=eint->areColinears();
11673               if(isColinear)
11674                 {
11675                   nbOfHit++;
11676                   posBaseElt--;
11677                   ret=true;
11678                 }
11679               delete eint;
11680               eCand->decrRef();
11681               if(!isColinear)
11682                 break;
11683             }
11684         }
11685       // Now move forward:
11686       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11687       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11688         {
11689           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11690           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11691           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11692           bool isColinear(eint->areColinears());
11693           if(isColinear)
11694             {
11695               nbOfHit++;
11696               posEndElt++;
11697               ret=true;
11698             }
11699           delete eint;
11700           eCand->decrRef();
11701           if(!isColinear)
11702               break;
11703         }
11704       //push [posBaseElt,posEndElt) in newConnOfCell using e
11705       // The if clauses below are (volontary) not mutually exclusive: on a quad cell with 2 edges, the end of the connectivity is also its begining!
11706       if(nbOfTurn==0)
11707         // at the begining of the connectivity (insert type)
11708         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11709       else if((nbOfHit+nbOfTurn) != (nbs-1))
11710         // in the middle
11711         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11712       if ((nbOfHit+nbOfTurn) == (nbs-1))
11713         // at the end (only quad points to deal with)
11714         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11715       posBaseElt=posEndElt;
11716       e->decrRef();
11717     }
11718   if(!middles.empty())
11719     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11720   return ret;
11721 }
11722
11723 /*!
11724  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11725  *
11726  * \return  int - the number of new nodes created.
11727  * \sa MEDCouplingUMesh::split2DCells
11728  */
11729 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11730 {
11731   checkConsistencyLight();
11732   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11733   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11734   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11735   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11736   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11737   const double *oldCoordsPtr(getCoords()->begin());
11738   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11739   int prevPosOfCi(ciPtr[0]);
11740   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11741     {
11742       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11743       for(int j=0;j<sz;j++)
11744         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11745       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11746       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11747         {
11748           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11749           if(sz2==0)
11750             {
11751               if(j<sz-1)
11752                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11753               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11754               continue;
11755             }
11756           std::vector<INTERP_KERNEL::Node *> ns(3);
11757           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11758           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11759           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11760           MCAuto<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11761           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11762             {
11763               cPtr[1]=subPtr[offset2+k];
11764               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11765             }
11766           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11767           if(j!=sz-1)
11768             { cPtr[1]=tmpEnd; }
11769           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11770         }
11771       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11772       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11773     }
11774   if(c->end()!=cPtr)
11775     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11776   _nodal_connec->decrRef();
11777   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11778   addCoo->rearrange(2);
11779   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11780   setCoords(coo);
11781   return addCoo->getNumberOfTuples();
11782 }
11783
11784 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11785 {
11786   if(nodalConnec && nodalConnecIndex)
11787     {
11788       types.clear();
11789       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11790       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11791       if(nbOfElem>0)
11792         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11793           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11794     }
11795 }
11796
11797 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11798     _own_cell(true),_cell_id(-1),_nb_cell(0)
11799 {
11800   if(mesh)
11801     {
11802       mesh->incrRef();
11803       _nb_cell=mesh->getNumberOfCells();
11804     }
11805 }
11806
11807 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11808 {
11809   if(_mesh)
11810     _mesh->decrRef();
11811   if(_own_cell)
11812     delete _cell;
11813 }
11814
11815 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11816     _own_cell(false),_cell_id(bg-1),
11817     _nb_cell(end)
11818 {
11819   if(mesh)
11820     mesh->incrRef();
11821 }
11822
11823 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11824 {
11825   _cell_id++;
11826   if(_cell_id<_nb_cell)
11827     {
11828       _cell->next();
11829       return _cell;
11830     }
11831   else
11832     return 0;
11833 }
11834
11835 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11836 {
11837   if(_mesh)
11838     _mesh->incrRef();
11839 }
11840
11841 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11842 {
11843   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11844 }
11845
11846 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11847 {
11848   if(_mesh)
11849     _mesh->decrRef();
11850 }
11851
11852 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11853     _itc(itc),
11854     _bg(bg),_end(end)
11855 {
11856   if(_mesh)
11857     _mesh->incrRef();
11858 }
11859
11860 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11861 {
11862   if(_mesh)
11863     _mesh->decrRef();
11864 }
11865
11866 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11867 {
11868   return _type;
11869 }
11870
11871 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11872 {
11873   return _end-_bg;
11874 }
11875
11876 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11877 {
11878   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11879 }
11880
11881 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11882 {
11883   if(mesh)
11884     {
11885       mesh->incrRef();
11886       _nb_cell=mesh->getNumberOfCells();
11887     }
11888 }
11889
11890 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11891 {
11892   if(_mesh)
11893     _mesh->decrRef();
11894   delete _cell;
11895 }
11896
11897 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11898 {
11899   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11900   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11901   if(_cell_id<_nb_cell)
11902     {
11903       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11904       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
11905       int startId=_cell_id;
11906       _cell_id+=nbOfElems;
11907       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11908     }
11909   else
11910     return 0;
11911 }
11912
11913 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11914 {
11915   if(mesh)
11916     {
11917       _conn=mesh->getNodalConnectivity()->getPointer();
11918       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11919     }
11920 }
11921
11922 void MEDCouplingUMeshCell::next()
11923 {
11924   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11925     {
11926       _conn+=_conn_lgth;
11927       _conn_indx++;
11928     }
11929   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11930 }
11931
11932 std::string MEDCouplingUMeshCell::repr() const
11933 {
11934   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11935     {
11936       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11937       oss << " : ";
11938       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11939       return oss.str();
11940     }
11941   else
11942     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11943 }
11944
11945 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11946 {
11947   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11948     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11949   else
11950     return INTERP_KERNEL::NORM_ERROR;
11951 }
11952
11953 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11954 {
11955   lgth=_conn_lgth;
11956   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11957     return _conn;
11958   else
11959     return 0;
11960 }