Salome HOME
Small modif
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2016  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 "MEDCouplingFieldDouble.hxx"
24 #include "MEDCouplingSkyLineArray.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DiameterCalculator.hxx"
33 #include "DirectedBoundingBox.hxx"
34 #include "InterpKernelMatrixTools.hxx"
35 #include "InterpKernelMeshQuality.hxx"
36 #include "InterpKernelCellSimplify.hxx"
37 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
38 #include "InterpKernelAutoPtr.hxx"
39 #include "InterpKernelGeo2DNode.hxx"
40 #include "InterpKernelGeo2DEdgeLin.hxx"
41 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
42 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
43
44 #include <sstream>
45 #include <fstream>
46 #include <numeric>
47 #include <cstring>
48 #include <limits>
49 #include <list>
50
51 using namespace MEDCoupling;
52
53 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
54
55 /// @cond INTERNAL
56 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 };
57 const int MEDCouplingUMesh::MEDCOUPLING2VTKTYPETRADUCER[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};
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());
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());
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());
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());
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());
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());
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());
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());
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 class MicroEdgesGenerator2D
677 {
678 public:
679   MicroEdgesGenerator2D(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
680   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfMicroEdges(); }
681   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillMicroEdgeNodalConnectivity(sonId,nodalConn,sonNodalConn,typeOfSon); }
682   static const int DELTA=1;
683 private:
684   const INTERP_KERNEL::CellModel& _cm;
685 };
686
687 class MicroEdgesGenerator3D
688 {
689 public:
690   MicroEdgesGenerator3D(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
691   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfMicroEdges(); }
692   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillMicroEdgeNodalConnectivity(sonId,nodalConn,sonNodalConn,typeOfSon); }
693   static const int DELTA=2;
694 private:
695   const INTERP_KERNEL::CellModel& _cm;
696 };
697
698 /// @endcond
699
700 /*!
701  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
702  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
703  * describing correspondence between cells of \a this and the result meshes are
704  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
705  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
706  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
707  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
708  * \warning For speed reasons, this method does not check if node ids in the nodal
709  *          connectivity correspond to the size of node coordinates array.
710  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
711  *          to write this mesh to the MED file, its cells must be sorted using
712  *          sortCellsInMEDFileFrmt().
713  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
714  *         each cell of \a this mesh.
715  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
716  *        dividing cell ids in \a desc into groups each referring to one
717  *        cell of \a this mesh. Its every element (except the last one) is an index
718  *        pointing to the first id of a group of cells. For example cells of the
719  *        result mesh bounding the cell #1 of \a this mesh are described by following
720  *        range of indices:
721  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
722  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
723  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
724  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
725  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
726  *         by each cell of the result mesh.
727  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
728  *        in the result mesh,
729  *        dividing cell ids in \a revDesc into groups each referring to one
730  *        cell of the result mesh the same way as \a descIndx divides \a desc.
731  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
732  *        delete this mesh using decrRef() as it is no more needed.
733  *  \throw If the coordinates array is not set.
734  *  \throw If the nodal connectivity of cells is node defined.
735  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
736  *         revDescIndx == NULL.
737  * 
738  *  \if ENABLE_EXAMPLES
739  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
740  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
741  *  \endif
742  * \sa buildDescendingConnectivity2()
743  */
744 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
745 {
746   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
747 }
748
749 /*!
750  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
751  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
752  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
753  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
754  * \sa MEDCouplingUMesh::buildDescendingConnectivity
755  */
756 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
757 {
758   checkFullyDefined();
759   if(getMeshDimension()!=3)
760     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
761   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
762 }
763
764 /*!
765  * This method computes the micro edges constituting each cell in \a this. Micro edge is an edge for non quadratic cells. Micro edge is an half edge for quadratic cells.
766  * This method works for both meshes with mesh dimenstion equal to 2 or 3. Dynamical cells are not supported (polygons, polyhedrons...)
767  * 
768  * \sa explode3DMeshTo1D, buildDescendingConnectiviy
769  */
770 MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
771 {
772    checkFullyDefined();
773    switch(getMeshDimension())
774      {
775      case 2:
776        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
777      case 3:
778        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
779      default:
780        throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explodeMeshIntoMicroEdges : Only 2D and 3D supported !");
781      }
782 }
783
784 /*!
785  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
786  * this->getMeshDimension(), that bound cells of \a this mesh. In
787  * addition arrays describing correspondence between cells of \a this and the result
788  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
789  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
790  *  mesh. This method differs from buildDescendingConnectivity() in that apart
791  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
792  * result meshes. So a positive id means that order of nodes in corresponding cells
793  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
794  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
795  * i.e. cell ids are one-based.
796  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
797  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
798  * \warning For speed reasons, this method does not check if node ids in the nodal
799  *          connectivity correspond to the size of node coordinates array.
800  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
801  *          to write this mesh to the MED file, its cells must be sorted using
802  *          sortCellsInMEDFileFrmt().
803  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
804  *         each cell of \a this mesh.
805  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
806  *        dividing cell ids in \a desc into groups each referring to one
807  *        cell of \a this mesh. Its every element (except the last one) is an index
808  *        pointing to the first id of a group of cells. For example cells of the
809  *        result mesh bounding the cell #1 of \a this mesh are described by following
810  *        range of indices:
811  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
812  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
813  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
814  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
815  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
816  *         by each cell of the result mesh.
817  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
818  *        in the result mesh,
819  *        dividing cell ids in \a revDesc into groups each referring to one
820  *        cell of the result mesh the same way as \a descIndx divides \a desc.
821  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
822  *        shares the node coordinates array with \a this mesh. The caller is to
823  *        delete this mesh using decrRef() as it is no more needed.
824  *  \throw If the coordinates array is not set.
825  *  \throw If the nodal connectivity of cells is node defined.
826  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
827  *         revDescIndx == NULL.
828  * 
829  *  \if ENABLE_EXAMPLES
830  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
831  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
832  *  \endif
833  * \sa buildDescendingConnectivity()
834  */
835 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
836 {
837   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
838 }
839
840 /*!
841  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
842  * For speed reasons no check of this will be done. This method calls
843  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
844  * This method lists cell by cell in \b this which are its neighbors. To compute the result
845  * only connectivities are considered.
846  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
847  * The format of return is hence \ref numbering-indirect.
848  *
849  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
850  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
851  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
852  * is equal to the last values in \b neighborsIndx.
853  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
854  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
855  */
856 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
857 {
858   MCAuto<DataArrayInt> desc=DataArrayInt::New();
859   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
860   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
861   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
862   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
863   meshDM1=0;
864   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
865 }
866
867 /*!
868  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
869  * of MEDCouplingUMesh::computeNeighborsOfCells.
870  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
871  * typically the case to extract a set a neighbours,
872  * excluding a set of meshdim-1 cells in input descending connectivity.
873  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
874  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
875  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
876  * are considered.
877  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
878  *
879  * \param [in] desc descending connectivity array.
880  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
881  * \param [in] revDesc reverse descending connectivity array.
882  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
883  * \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
884  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
885  * \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.
886  */
887 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
888                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
889 {
890   if(!desc || !descIndx || !revDesc || !revDescIndx)
891     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
892   const int *descPtr=desc->getConstPointer();
893   const int *descIPtr=descIndx->getConstPointer();
894   const int *revDescPtr=revDesc->getConstPointer();
895   const int *revDescIPtr=revDescIndx->getConstPointer();
896   //
897   int nbCells=descIndx->getNumberOfTuples()-1;
898   MCAuto<DataArrayInt> out0=DataArrayInt::New();
899   MCAuto<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
900   int *out1Ptr=out1->getPointer();
901   *out1Ptr++=0;
902   out0->reserve(desc->getNumberOfTuples());
903   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
904     {
905       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
906         {
907           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
908           s.erase(i);
909           out0->insertAtTheEnd(s.begin(),s.end());
910         }
911       *out1Ptr=out0->getNumberOfTuples();
912     }
913   neighbors=out0.retn();
914   neighborsIndx=out1.retn();
915 }
916
917 /*!
918  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
919  * For speed reasons no check of this will be done. This method calls
920  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
921  * This method lists node by node in \b this which are its neighbors. To compute the result
922  * only connectivities are considered.
923  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
924  *
925  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
926  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
927  * parameter allows to select the right part in this array (\ref numbering-indirect).
928  * The number of tuples is equal to the last values in \b neighborsIndx.
929  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
930  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
931  */
932 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
933 {
934   checkFullyDefined();
935   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
936   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
937   MCAuto<MEDCouplingUMesh> mesh1D;
938   switch(mdim)
939   {
940     case 3:
941       {
942         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
943         break;
944       }
945     case 2:
946       {
947         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
948         break;
949       }
950     case 1:
951       {
952         mesh1D=const_cast<MEDCouplingUMesh *>(this);
953         mesh1D->incrRef();
954         break;
955       }
956     default:
957       {
958         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
959       }
960   }
961   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
962   mesh1D->getReverseNodalConnectivity(desc,descIndx);
963   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
964   ret0->alloc(desc->getNumberOfTuples(),1);
965   int *r0Pt(ret0->getPointer());
966   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
967   for(int i=0;i<nbNodes;i++,rni++)
968     {
969       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
970         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
971     }
972   neighbors=ret0.retn();
973   neighborsIdx=descIndx.retn();
974 }
975
976 /// @cond INTERNAL
977
978 /*!
979  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
980  * For speed reasons no check of this will be done.
981  */
982 template<class SonsGenerator>
983 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
984 {
985   if(!desc || !descIndx || !revDesc || !revDescIndx)
986     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
987   checkConnectivityFullyDefined();
988   int nbOfCells=getNumberOfCells();
989   int nbOfNodes=getNumberOfNodes();
990   MCAuto<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
991   int *revNodalIndxPtr=revNodalIndx->getPointer();
992   const int *conn=_nodal_connec->getConstPointer();
993   const int *connIndex=_nodal_connec_index->getConstPointer();
994   std::string name="Mesh constituent of "; name+=getName();
995   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
996   ret->setCoords(getCoords());
997   ret->allocateCells(2*nbOfCells);
998   descIndx->alloc(nbOfCells+1,1);
999   MCAuto<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
1000   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
1001   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
1002     {
1003       int pos=connIndex[eltId];
1004       int posP1=connIndex[eltId+1];
1005       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
1006       SonsGenerator sg(cm);
1007       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
1008       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
1009       for(unsigned i=0;i<nbOfSons;i++)
1010         {
1011           INTERP_KERNEL::NormalizedCellType cmsId;
1012           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
1013           for(unsigned k=0;k<nbOfNodesSon;k++)
1014             if(tmp[k]>=0)
1015               revNodalIndxPtr[tmp[k]+1]++;
1016           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
1017           revDesc2->pushBackSilent(eltId);
1018         }
1019       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
1020     }
1021   int nbOfCellsM1=ret->getNumberOfCells();
1022   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
1023   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
1024   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
1025   int *revNodalPtr=revNodal->getPointer();
1026   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
1027   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
1028   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
1029     {
1030       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
1031       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
1032       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
1033         if(*iter>=0)//for polyhedrons
1034           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
1035     }
1036   //
1037   DataArrayInt *commonCells=0,*commonCellsI=0;
1038   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1039   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1040   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1041   int newNbOfCellsM1=-1;
1042   MCAuto<DataArrayInt> o2nM1=DataArrayInt::ConvertIndexArrayToO2N(nbOfCellsM1,commonCells->begin(),
1043                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1044   std::vector<bool> isImpacted(nbOfCellsM1,false);
1045   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1046     for(int work2=work[0];work2!=work[1];work2++)
1047       isImpacted[commonCellsPtr[work2]]=true;
1048   const int *o2nM1Ptr=o2nM1->getConstPointer();
1049   MCAuto<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1050   const int *n2oM1Ptr=n2oM1->getConstPointer();
1051   MCAuto<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1052   ret2->copyTinyInfoFrom(this);
1053   desc->alloc(descIndx->back(),1);
1054   int *descPtr=desc->getPointer();
1055   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1056   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1057     {
1058       if(!isImpacted[i])
1059         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1060       else
1061         {
1062           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1063             {
1064               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1065               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1066             }
1067           else
1068             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1069         }
1070     }
1071   revDesc->reserve(newNbOfCellsM1);
1072   revDescIndx->alloc(newNbOfCellsM1+1,1);
1073   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1074   const int *revDesc2Ptr=revDesc2->getConstPointer();
1075   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1076     {
1077       int oldCellIdM1=n2oM1Ptr[i];
1078       if(!isImpacted[oldCellIdM1])
1079         {
1080           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1081           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1082         }
1083       else
1084         {
1085           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1086             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1087           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1088           commonCellsIPtr++;
1089         }
1090     }
1091   //
1092   return ret2.retn();
1093 }
1094
1095 struct MEDCouplingAccVisit
1096 {
1097   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1098   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1099   int _new_nb_of_nodes;
1100 };
1101
1102 /// @endcond
1103
1104 /*!
1105  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1106  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1107  * array of cell ids. Pay attention that after conversion all algorithms work slower
1108  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1109  * conversion due presence of invalid ids in the array of cells to convert, as a
1110  * result \a this mesh contains some already converted elements. In this case the 2D
1111  * mesh remains valid but 3D mesh becomes \b inconsistent!
1112  *  \warning This method can significantly modify the order of geometric types in \a this,
1113  *          hence, to write this mesh to the MED file, its cells must be sorted using
1114  *          sortCellsInMEDFileFrmt().
1115  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1116  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1117  *         cellIdsToConvertBg.
1118  *  \throw If the coordinates array is not set.
1119  *  \throw If the nodal connectivity of cells is node defined.
1120  *  \throw If dimension of \a this mesh is not either 2 or 3.
1121  *
1122  *  \if ENABLE_EXAMPLES
1123  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1124  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1125  *  \endif
1126  */
1127 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1128 {
1129   checkFullyDefined();
1130   int dim=getMeshDimension();
1131   if(dim<2 || dim>3)
1132     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1133   int nbOfCells(getNumberOfCells());
1134   if(dim==2)
1135     {
1136       const int *connIndex=_nodal_connec_index->getConstPointer();
1137       int *conn=_nodal_connec->getPointer();
1138       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1139         {
1140           if(*iter>=0 && *iter<nbOfCells)
1141             {
1142               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1143               if(!cm.isQuadratic())
1144                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1145               else
1146                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1147             }
1148           else
1149             {
1150               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1151               oss << " in range [0," << nbOfCells << ") !";
1152               throw INTERP_KERNEL::Exception(oss.str());
1153             }
1154         }
1155     }
1156   else
1157     {
1158       int *connIndex(_nodal_connec_index->getPointer());
1159       const int *connOld(_nodal_connec->getConstPointer());
1160       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1161       std::vector<bool> toBeDone(nbOfCells,false);
1162       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1163         {
1164           if(*iter>=0 && *iter<nbOfCells)
1165             toBeDone[*iter]=true;
1166           else
1167             {
1168               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1169               oss << " in range [0," << nbOfCells << ") !";
1170               throw INTERP_KERNEL::Exception(oss.str());
1171             }
1172         }
1173       for(int cellId=0;cellId<nbOfCells;cellId++)
1174         {
1175           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1176           int lgthOld(posP1-pos-1);
1177           if(toBeDone[cellId])
1178             {
1179               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1180               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1181               int *tmp(new int[nbOfFaces*lgthOld+1]);
1182               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1183               for(unsigned j=0;j<nbOfFaces;j++)
1184                 {
1185                   INTERP_KERNEL::NormalizedCellType type;
1186                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1187                   work+=offset;
1188                   *work++=-1;
1189                 }
1190               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1191               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1192               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1193               delete [] tmp;
1194             }
1195           else
1196             {
1197               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1198               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1199             }
1200         }
1201       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1202     }
1203   computeTypes();
1204 }
1205
1206 /*!
1207  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1208  * polyhedrons (if \a this is a 3D mesh).
1209  *  \warning As this method is purely for user-friendliness and no optimization is
1210  *          done to avoid construction of a useless vector, this method can be costly
1211  *          in memory.
1212  *  \throw If the coordinates array is not set.
1213  *  \throw If the nodal connectivity of cells is node defined.
1214  *  \throw If dimension of \a this mesh is not either 2 or 3.
1215  */
1216 void MEDCouplingUMesh::convertAllToPoly()
1217 {
1218   int nbOfCells=getNumberOfCells();
1219   std::vector<int> cellIds(nbOfCells);
1220   for(int i=0;i<nbOfCells;i++)
1221     cellIds[i]=i;
1222   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1223 }
1224
1225 /*!
1226  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1227  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1228  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1229  * base facet of the volume and the second half of nodes describes an opposite facet
1230  * having the same number of nodes as the base one. This method converts such
1231  * connectivity to a valid polyhedral format where connectivity of each facet is
1232  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1233  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1234  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1235  * a correct orientation of the first facet of a polyhedron, else orientation of a
1236  * corrected cell is reverse.<br>
1237  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1238  * it releases the user from boring description of polyhedra connectivity in the valid
1239  * format.
1240  *  \throw If \a this->getMeshDimension() != 3.
1241  *  \throw If \a this->getSpaceDimension() != 3.
1242  *  \throw If the nodal connectivity of cells is not defined.
1243  *  \throw If the coordinates array is not set.
1244  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1245  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1246  *
1247  *  \if ENABLE_EXAMPLES
1248  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1249  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1250  *  \endif
1251  */
1252 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1253 {
1254   checkFullyDefined();
1255   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1256     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1257   int nbOfCells=getNumberOfCells();
1258   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1259   newCi->alloc(nbOfCells+1,1);
1260   int *newci=newCi->getPointer();
1261   const int *ci=_nodal_connec_index->getConstPointer();
1262   const int *c=_nodal_connec->getConstPointer();
1263   newci[0]=0;
1264   for(int i=0;i<nbOfCells;i++)
1265     {
1266       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1267       if(type==INTERP_KERNEL::NORM_POLYHED)
1268         {
1269           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1270             {
1271               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1272               throw INTERP_KERNEL::Exception(oss.str());
1273             }
1274           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1275           if(n2%2!=0)
1276             {
1277               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 !";
1278               throw INTERP_KERNEL::Exception(oss.str());
1279             }
1280           int n1=(int)(n2/2);
1281           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)
1282         }
1283       else
1284         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1285     }
1286   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1287   newC->alloc(newci[nbOfCells],1);
1288   int *newc=newC->getPointer();
1289   for(int i=0;i<nbOfCells;i++)
1290     {
1291       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1292       if(type==INTERP_KERNEL::NORM_POLYHED)
1293         {
1294           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1295           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1296           *newc++=-1;
1297           for(std::size_t j=0;j<n1;j++)
1298             {
1299               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1300               newc[n1+5*j]=-1;
1301               newc[n1+5*j+1]=c[ci[i]+1+j];
1302               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1303               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1304               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1305             }
1306           newc+=n1*6;
1307         }
1308       else
1309         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1310     }
1311   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1312   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1313 }
1314
1315
1316 /*!
1317  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1318  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1319  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1320  *          to write this mesh to the MED file, its cells must be sorted using
1321  *          sortCellsInMEDFileFrmt().
1322  * \warning Cells (and most notably polyhedrons) must be correctly oriented for this to work
1323  *          properly. See orientCorrectlyPolyhedrons() and arePolyhedronsNotCorrectlyOriented().
1324  * \return \c true if at least one cell has been converted, \c false else. In the
1325  *         last case the nodal connectivity remains unchanged.
1326  * \throw If the coordinates array is not set.
1327  * \throw If the nodal connectivity of cells is not defined.
1328  * \throw If \a this->getMeshDimension() < 0.
1329  */
1330 bool MEDCouplingUMesh::unPolyze()
1331 {
1332   checkFullyDefined();
1333   int mdim=getMeshDimension();
1334   if(mdim<0)
1335     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1336   if(mdim<=1)
1337     return false;
1338   int nbOfCells=getNumberOfCells();
1339   if(nbOfCells<1)
1340     return false;
1341   int initMeshLgth=getNodalConnectivityArrayLen();
1342   int *conn=_nodal_connec->getPointer();
1343   int *index=_nodal_connec_index->getPointer();
1344   int posOfCurCell=0;
1345   int newPos=0;
1346   int lgthOfCurCell;
1347   bool ret=false;
1348   for(int i=0;i<nbOfCells;i++)
1349     {
1350       lgthOfCurCell=index[i+1]-posOfCurCell;
1351       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1352       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1353       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1354       int newLgth;
1355       if(cm.isDynamic())
1356         {
1357           switch(cm.getDimension())
1358           {
1359             case 2:
1360               {
1361                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1362                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1363                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1364                 break;
1365               }
1366             case 3:
1367               {
1368                 int nbOfFaces,lgthOfPolyhConn;
1369                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1370                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1371                 break;
1372               }
1373             case 1:
1374               {
1375                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1376                 break;
1377               }
1378           }
1379           ret=ret || (newType!=type);
1380           conn[newPos]=newType;
1381           newPos+=newLgth+1;
1382           posOfCurCell=index[i+1];
1383           index[i+1]=newPos;
1384         }
1385       else
1386         {
1387           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1388           newPos+=lgthOfCurCell;
1389           posOfCurCell+=lgthOfCurCell;
1390           index[i+1]=newPos;
1391         }
1392     }
1393   if(newPos!=initMeshLgth)
1394     _nodal_connec->reAlloc(newPos);
1395   if(ret)
1396     computeTypes();
1397   return ret;
1398 }
1399
1400 /*!
1401  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1402  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1403  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1404  *
1405  * \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 
1406  *             precision.
1407  */
1408 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1409 {
1410   checkFullyDefined();
1411   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1412     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1413   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1414   coords->recenterForMaxPrecision(eps);
1415   //
1416   int nbOfCells=getNumberOfCells();
1417   const int *conn=_nodal_connec->getConstPointer();
1418   const int *index=_nodal_connec_index->getConstPointer();
1419   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1420   connINew->alloc(nbOfCells+1,1);
1421   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1422   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1423   bool changed=false;
1424   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1425     {
1426       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1427         {
1428           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1429           changed=true;
1430         }
1431       else
1432         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1433       *connINewPtr=connNew->getNumberOfTuples();
1434     }
1435   if(changed)
1436     setConnectivity(connNew,connINew,false);
1437 }
1438
1439 /*!
1440  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1441  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1442  * the format of the returned DataArrayInt instance.
1443  * 
1444  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1445  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1446  */
1447 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1448 {
1449   checkConnectivityFullyDefined();
1450   const int *maxEltPt(std::max_element(_nodal_connec->begin(),_nodal_connec->end()));
1451   int maxElt(maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1);
1452   std::vector<bool> retS(maxElt,false);
1453   computeNodeIdsAlg(retS);
1454   return DataArrayInt::BuildListOfSwitchedOn(retS);
1455 }
1456
1457 /*!
1458  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1459  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1460  */
1461 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1462 {
1463   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1464   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1465   for(int i=0;i<nbOfCells;i++)
1466     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1467       if(conn[j]>=0)
1468         {
1469           if(conn[j]<nbOfNodes)
1470             nodeIdsInUse[conn[j]]=true;
1471           else
1472             {
1473               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1474               throw INTERP_KERNEL::Exception(oss.str());
1475             }
1476         }
1477 }
1478
1479 /*!
1480  * Finds nodes not used in any cell and returns an array giving a new id to every node
1481  * by excluding the unused nodes, for which the array holds -1. The result array is
1482  * a mapping in "Old to New" mode. 
1483  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1484  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1485  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1486  *          if the node is unused or a new id else. The caller is to delete this
1487  *          array using decrRef() as it is no more needed.  
1488  *  \throw If the coordinates array is not set.
1489  *  \throw If the nodal connectivity of cells is not defined.
1490  *  \throw If the nodal connectivity includes an invalid id.
1491  *
1492  *  \if ENABLE_EXAMPLES
1493  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1494  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1495  *  \endif
1496  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1497  */
1498 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1499 {
1500   nbrOfNodesInUse=-1;
1501   int nbOfNodes(getNumberOfNodes());
1502   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1503   ret->alloc(nbOfNodes,1);
1504   int *traducer=ret->getPointer();
1505   std::fill(traducer,traducer+nbOfNodes,-1);
1506   int nbOfCells=getNumberOfCells();
1507   const int *connIndex=_nodal_connec_index->getConstPointer();
1508   const int *conn=_nodal_connec->getConstPointer();
1509   for(int i=0;i<nbOfCells;i++)
1510     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1511       if(conn[j]>=0)
1512         {
1513           if(conn[j]<nbOfNodes)
1514             traducer[conn[j]]=1;
1515           else
1516             {
1517               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1518               throw INTERP_KERNEL::Exception(oss.str());
1519             }
1520         }
1521   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1522   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1523   return ret.retn();
1524 }
1525
1526 /*!
1527  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1528  * For each cell in \b this the number of nodes constituting cell is computed.
1529  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1530  * So for pohyhedrons some nodes can be counted several times in the returned result.
1531  * 
1532  * \return a newly allocated array
1533  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1534  */
1535 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1536 {
1537   checkConnectivityFullyDefined();
1538   int nbOfCells=getNumberOfCells();
1539   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1540   ret->alloc(nbOfCells,1);
1541   int *retPtr=ret->getPointer();
1542   const int *conn=getNodalConnectivity()->getConstPointer();
1543   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1544   for(int i=0;i<nbOfCells;i++,retPtr++)
1545     {
1546       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1547         *retPtr=connI[i+1]-connI[i]-1;
1548       else
1549         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1550     }
1551   return ret.retn();
1552 }
1553
1554 /*!
1555  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1556  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1557  *
1558  * \return DataArrayInt * - new object to be deallocated by the caller.
1559  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1560  */
1561 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1562 {
1563   checkConnectivityFullyDefined();
1564   int nbOfCells=getNumberOfCells();
1565   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1566   ret->alloc(nbOfCells,1);
1567   int *retPtr=ret->getPointer();
1568   const int *conn=getNodalConnectivity()->getConstPointer();
1569   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1570   for(int i=0;i<nbOfCells;i++,retPtr++)
1571     {
1572       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1573       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1574         *retPtr=(int)s.size();
1575       else
1576         {
1577           s.erase(-1);
1578           *retPtr=(int)s.size();
1579         }
1580     }
1581   return ret.retn();
1582 }
1583
1584 /*!
1585  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1586  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1587  * 
1588  * \return a newly allocated array
1589  */
1590 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1591 {
1592   checkConnectivityFullyDefined();
1593   int nbOfCells=getNumberOfCells();
1594   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1595   ret->alloc(nbOfCells,1);
1596   int *retPtr=ret->getPointer();
1597   const int *conn=getNodalConnectivity()->getConstPointer();
1598   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1599   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1600     {
1601       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1602       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1603     }
1604   return ret.retn();
1605 }
1606
1607 /*!
1608  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1609  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1610  * array mean that the corresponding old node is no more used. 
1611  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1612  *           this->getNumberOfNodes() before call of this method. The caller is to
1613  *           delete this array using decrRef() as it is no more needed. 
1614  *  \throw If the coordinates array is not set.
1615  *  \throw If the nodal connectivity of cells is not defined.
1616  *  \throw If the nodal connectivity includes an invalid id.
1617  *  \sa areAllNodesFetched
1618  *
1619  *  \if ENABLE_EXAMPLES
1620  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1621  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1622  *  \endif
1623  */
1624 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1625 {
1626   return MEDCouplingPointSet::zipCoordsTraducer();
1627 }
1628
1629 /*!
1630  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1631  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1632  */
1633 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1634 {
1635   switch(compType)
1636   {
1637     case 0:
1638       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1639     case 1:
1640       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1641     case 2:
1642       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1643     case 3:
1644       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1645     case 7:
1646       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1647   }
1648   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1649 }
1650
1651 /*!
1652  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1653  */
1654 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1655 {
1656   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1657     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1658   return 0;
1659 }
1660
1661 /*!
1662  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1663  */
1664 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1665 {
1666   int sz=connI[cell1+1]-connI[cell1];
1667   if(sz==connI[cell2+1]-connI[cell2])
1668     {
1669       if(conn[connI[cell1]]==conn[connI[cell2]])
1670         {
1671           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1672           unsigned dim=cm.getDimension();
1673           if(dim!=3)
1674             {
1675               if(dim!=1)
1676                 {
1677                   int sz1=2*(sz-1);
1678                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1679                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1680                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1681                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1682                   return work!=tmp+sz1?1:0;
1683                 }
1684               else
1685                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1686             }
1687           else
1688             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1689         }
1690     }
1691   return 0;
1692 }
1693
1694 /*!
1695  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1696  */
1697 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1698 {
1699   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1700     {
1701       if(conn[connI[cell1]]==conn[connI[cell2]])
1702         {
1703           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1704           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1705           return s1==s2?1:0;
1706         }
1707     }
1708   return 0;
1709 }
1710
1711 /*!
1712  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1713  */
1714 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1715 {
1716   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1717     {
1718       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1719       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1720       return s1==s2?1:0;
1721     }
1722   return 0;
1723 }
1724
1725 /*!
1726  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1727  */
1728 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1729 {
1730   int sz=connI[cell1+1]-connI[cell1];
1731   if(sz==connI[cell2+1]-connI[cell2])
1732     {
1733       if(conn[connI[cell1]]==conn[connI[cell2]])
1734         {
1735           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1736           unsigned dim=cm.getDimension();
1737           if(dim!=3)
1738             {
1739               if(dim!=1)
1740                 {
1741                   int sz1=2*(sz-1);
1742                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1743                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1744                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1745                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1746                   if(work!=tmp+sz1)
1747                     return 1;
1748                   else
1749                     {
1750                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1751                       std::reverse_iterator<int *> it2((int *)tmp);
1752                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1753                         return 2;
1754                       else
1755                         return 0;
1756                     }
1757
1758                   return work!=tmp+sz1?1:0;
1759                 }
1760               else
1761                 {//case of SEG2 and SEG3
1762                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1763                     return 1;
1764                   if(!cm.isQuadratic())
1765                     {
1766                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1767                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1768                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1769                         return 2;
1770                       return 0;
1771                     }
1772                   else
1773                     {
1774                       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])
1775                         return 2;
1776                       return 0;
1777                     }
1778                 }
1779             }
1780           else
1781             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1782         }
1783     }
1784   return 0;
1785 }
1786
1787 /*!
1788  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1789  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1790  * and result remains unchanged.
1791  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1792  * If in 'candidates' pool -1 value is considered as an empty value.
1793  * WARNING this method returns only ONE set of result !
1794  */
1795 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1796 {
1797   if(candidates.size()<1)
1798     return false;
1799   bool ret=false;
1800   std::vector<int>::const_iterator iter=candidates.begin();
1801   int start=(*iter++);
1802   for(;iter!=candidates.end();iter++)
1803     {
1804       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1805       if(status!=0)
1806         {
1807           if(!ret)
1808             {
1809               result->pushBackSilent(start);
1810               ret=true;
1811             }
1812           if(status==1)
1813             result->pushBackSilent(*iter);
1814           else
1815             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1816         }
1817     }
1818   return ret;
1819 }
1820
1821 /*!
1822  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1823  * by \a compType.
1824  * This method keeps the coordiantes of \a this. This method is time consuming.
1825  *
1826  * \param [in] compType input specifying the technique used to compare cells each other.
1827  *   - 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.
1828  *   - 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)
1829  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1830  *   - 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
1831  * can be used for users not sensitive to orientation of cell
1832  * \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.
1833  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1834  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1835  * \return the correspondance array old to new in a newly allocated array.
1836  * 
1837  */
1838 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1839 {
1840   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1841   getReverseNodalConnectivity(revNodal,revNodalI);
1842   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1843 }
1844
1845 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1846                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1847 {
1848   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1849   int nbOfCells=nodalI->getNumberOfTuples()-1;
1850   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1851   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1852   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1853   std::vector<bool> isFetched(nbOfCells,false);
1854   if(startCellId==0)
1855     {
1856       for(int i=0;i<nbOfCells;i++)
1857         {
1858           if(!isFetched[i])
1859             {
1860               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1861               std::vector<int> v,v2;
1862               if(connOfNode!=connPtr+connIPtr[i+1])
1863                 {
1864                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1865                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1866                   connOfNode++;
1867                 }
1868               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1869                 if(*connOfNode>=0)
1870                   {
1871                     v=v2;
1872                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1873                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1874                     v2.resize(std::distance(v2.begin(),it));
1875                   }
1876               if(v2.size()>1)
1877                 {
1878                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1879                     {
1880                       int pos=commonCellsI->back();
1881                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1882                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1883                         isFetched[*it]=true;
1884                     }
1885                 }
1886             }
1887         }
1888     }
1889   else
1890     {
1891       for(int i=startCellId;i<nbOfCells;i++)
1892         {
1893           if(!isFetched[i])
1894             {
1895               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1896               std::vector<int> v,v2;
1897               if(connOfNode!=connPtr+connIPtr[i+1])
1898                 {
1899                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1900                   connOfNode++;
1901                 }
1902               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1903                 if(*connOfNode>=0)
1904                   {
1905                     v=v2;
1906                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1907                     v2.resize(std::distance(v2.begin(),it));
1908                   }
1909               if(v2.size()>1)
1910                 {
1911                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1912                     {
1913                       int pos=commonCellsI->back();
1914                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1915                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1916                         isFetched[*it]=true;
1917                     }
1918                 }
1919             }
1920         }
1921     }
1922   commonCellsArr=commonCells.retn();
1923   commonCellsIArr=commonCellsI.retn();
1924 }
1925
1926 /*!
1927  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1928  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1929  * than \a this->getNumberOfCells() in the returned array means that there is no
1930  * corresponding cell in \a this mesh.
1931  * It is expected that \a this and \a other meshes share the same node coordinates
1932  * array, if it is not so an exception is thrown. 
1933  *  \param [in] other - the mesh to compare with.
1934  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1935  *         valid values [0,1,2], see zipConnectivityTraducer().
1936  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1937  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1938  *         values. The caller is to delete this array using
1939  *         decrRef() as it is no more needed.
1940  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1941  *         mesh.
1942  *
1943  *  \if ENABLE_EXAMPLES
1944  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1945  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1946  *  \endif
1947  *  \sa checkDeepEquivalOnSameNodesWith()
1948  *  \sa checkGeoEquivalWith()
1949  */
1950 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1951 {
1952   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1953   int nbOfCells=getNumberOfCells();
1954   static const int possibleCompType[]={0,1,2};
1955   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1956     {
1957       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1958       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1959       oss << " !";
1960       throw INTERP_KERNEL::Exception(oss.str());
1961     }
1962   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1963   arr=o2n->subArray(nbOfCells);
1964   arr->setName(other->getName());
1965   int tmp;
1966   if(other->getNumberOfCells()==0)
1967     return true;
1968   return arr->getMaxValue(tmp)<nbOfCells;
1969 }
1970
1971 /*!
1972  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1973  * This method tries to determine if \b other is fully included in \b this.
1974  * The main difference is that this method is not expected to throw exception.
1975  * This method has two outputs :
1976  *
1977  * \param other other mesh
1978  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1979  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1980  */
1981 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1982 {
1983   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1984   DataArrayInt *commonCells=0,*commonCellsI=0;
1985   int thisNbCells=getNumberOfCells();
1986   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1987   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1988   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1989   int otherNbCells=other->getNumberOfCells();
1990   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1991   arr2->alloc(otherNbCells,1);
1992   arr2->fillWithZero();
1993   int *arr2Ptr=arr2->getPointer();
1994   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1995   for(int i=0;i<nbOfCommon;i++)
1996     {
1997       int start=commonCellsPtr[commonCellsIPtr[i]];
1998       if(start<thisNbCells)
1999         {
2000           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
2001             {
2002               int sig=commonCellsPtr[j]>0?1:-1;
2003               int val=std::abs(commonCellsPtr[j])-1;
2004               if(val>=thisNbCells)
2005                 arr2Ptr[val-thisNbCells]=sig*(start+1);
2006             }
2007         }
2008     }
2009   arr2->setName(other->getName());
2010   if(arr2->presenceOfValue(0))
2011     return false;
2012   arr=arr2.retn();
2013   return true;
2014 }
2015
2016 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
2017 {
2018   if(!other)
2019     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
2020   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
2021   if(!otherC)
2022     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
2023   std::vector<const MEDCouplingUMesh *> ms(2);
2024   ms[0]=this;
2025   ms[1]=otherC;
2026   return MergeUMeshesOnSameCoords(ms);
2027 }
2028
2029 /*!
2030  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2031  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2032  * cellIds is not given explicitely but by a range python like.
2033  * 
2034  * \param start
2035  * \param end
2036  * \param step
2037  * \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.
2038  * \return a newly allocated
2039  * 
2040  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2041  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2042  */
2043 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
2044 {
2045   if(getMeshDimension()!=-1)
2046     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
2047   else
2048     {
2049       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
2050       if(newNbOfCells!=1)
2051         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2052       if(start!=0)
2053         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2054       incrRef();
2055       return const_cast<MEDCouplingUMesh *>(this);
2056     }
2057 }
2058
2059 /*!
2060  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2061  * The result mesh shares or not the node coordinates array with \a this mesh depending
2062  * on \a keepCoords parameter.
2063  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2064  *           to write this mesh to the MED file, its cells must be sorted using
2065  *           sortCellsInMEDFileFrmt().
2066  *  \param [in] begin - an array of cell ids to include to the new mesh.
2067  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2068  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2069  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2070  *         by calling zipCoords().
2071  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2072  *         to delete this mesh using decrRef() as it is no more needed. 
2073  *  \throw If the coordinates array is not set.
2074  *  \throw If the nodal connectivity of cells is not defined.
2075  *  \throw If any cell id in the array \a begin is not valid.
2076  *
2077  *  \if ENABLE_EXAMPLES
2078  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2079  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2080  *  \endif
2081  */
2082 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2083 {
2084   if(getMeshDimension()!=-1)
2085     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2086   else
2087     {
2088       if(end-begin!=1)
2089         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2090       if(begin[0]!=0)
2091         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2092       incrRef();
2093       return const_cast<MEDCouplingUMesh *>(this);
2094     }
2095 }
2096
2097 /*!
2098  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2099  *
2100  * 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.
2101  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2102  * The number of cells of \b this will remain the same with this method.
2103  *
2104  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2105  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2106  * \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 ).
2107  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2108  */
2109 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2110 {
2111   checkConnectivityFullyDefined();
2112   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2113   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2115   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2116     {
2117       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2118       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2119       throw INTERP_KERNEL::Exception(oss.str());
2120     }
2121   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2122   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2123     {
2124       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2125       throw INTERP_KERNEL::Exception(oss.str());
2126     }
2127   int nbOfCells=getNumberOfCells();
2128   bool easyAssign=true;
2129   const int *connI=_nodal_connec_index->getConstPointer();
2130   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2131   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2132     {
2133       if(*it>=0 && *it<nbOfCells)
2134         {
2135           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2136         }
2137       else
2138         {
2139           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2140           throw INTERP_KERNEL::Exception(oss.str());
2141         }
2142     }
2143   if(easyAssign)
2144     {
2145       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2146       computeTypes();
2147     }
2148   else
2149     {
2150       DataArrayInt *arrOut=0,*arrIOut=0;
2151       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2152                                                arrOut,arrIOut);
2153       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2154       setConnectivity(arrOut,arrIOut,true);
2155     }
2156 }
2157
2158 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2159 {
2160   checkConnectivityFullyDefined();
2161   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2162   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2163     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2164   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2165     {
2166       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2167       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2168       throw INTERP_KERNEL::Exception(oss.str());
2169     }
2170   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2171   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2172     {
2173       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2174       throw INTERP_KERNEL::Exception(oss.str());
2175     }
2176   int nbOfCells=getNumberOfCells();
2177   bool easyAssign=true;
2178   const int *connI=_nodal_connec_index->getConstPointer();
2179   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2180   int it=start;
2181   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2182     {
2183       if(it>=0 && it<nbOfCells)
2184         {
2185           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2186         }
2187       else
2188         {
2189           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2190           throw INTERP_KERNEL::Exception(oss.str());
2191         }
2192     }
2193   if(easyAssign)
2194     {
2195       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2196       computeTypes();
2197     }
2198   else
2199     {
2200       DataArrayInt *arrOut=0,*arrIOut=0;
2201       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2202                                                 arrOut,arrIOut);
2203       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2204       setConnectivity(arrOut,arrIOut,true);
2205     }
2206 }                      
2207
2208 /*!
2209  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2210  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2211  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2212  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2213  *
2214  * \param [in] begin input start of array of node ids.
2215  * \param [in] end input end of array of node ids.
2216  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2217  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2218  */
2219 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2220 {
2221   MCAuto<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2222   checkConnectivityFullyDefined();
2223   int tmp=-1;
2224   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2225   std::vector<bool> fastFinder(sz,false);
2226   for(const int *work=begin;work!=end;work++)
2227     if(*work>=0 && *work<sz)
2228       fastFinder[*work]=true;
2229   int nbOfCells=getNumberOfCells();
2230   const int *conn=getNodalConnectivity()->getConstPointer();
2231   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2232   for(int i=0;i<nbOfCells;i++)
2233     {
2234       int ref=0,nbOfHit=0;
2235       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2236         if(*work2>=0)
2237           {
2238             ref++;
2239             if(fastFinder[*work2])
2240               nbOfHit++;
2241           }
2242       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2243         cellIdsKept->pushBackSilent(i);
2244     }
2245   cellIdsKeptArr=cellIdsKept.retn();
2246 }
2247
2248 /*!
2249  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2250  * this->getMeshDimension(), that bound some cells of \a this mesh.
2251  * The cells of lower dimension to include to the result mesh are selected basing on
2252  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2253  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2254  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2255  * created mesh shares the node coordinates array with \a this mesh. 
2256  *  \param [in] begin - the array of node ids.
2257  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2258  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2259  *         array \a begin are added, else cells whose any node is in the
2260  *         array \a begin are added.
2261  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2262  *         to delete this mesh using decrRef() as it is no more needed. 
2263  *  \throw If the coordinates array is not set.
2264  *  \throw If the nodal connectivity of cells is not defined.
2265  *  \throw If any node id in \a begin is not valid.
2266  *
2267  *  \if ENABLE_EXAMPLES
2268  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2269  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2270  *  \endif
2271  */
2272 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2273 {
2274   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2275   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2276   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2277   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2278   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2279 }
2280
2281 /*!
2282  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2283  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2284  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2285  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2286  *         by calling zipCoords().
2287  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2288  *         to delete this mesh using decrRef() as it is no more needed. 
2289  *  \throw If the coordinates array is not set.
2290  *  \throw If the nodal connectivity of cells is not defined.
2291  *
2292  *  \if ENABLE_EXAMPLES
2293  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2294  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2295  *  \endif
2296  */
2297 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2298 {
2299   DataArrayInt *desc=DataArrayInt::New();
2300   DataArrayInt *descIndx=DataArrayInt::New();
2301   DataArrayInt *revDesc=DataArrayInt::New();
2302   DataArrayInt *revDescIndx=DataArrayInt::New();
2303   //
2304   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2305   revDesc->decrRef();
2306   desc->decrRef();
2307   descIndx->decrRef();
2308   int nbOfCells=meshDM1->getNumberOfCells();
2309   const int *revDescIndxC=revDescIndx->getConstPointer();
2310   std::vector<int> boundaryCells;
2311   for(int i=0;i<nbOfCells;i++)
2312     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2313       boundaryCells.push_back(i);
2314   revDescIndx->decrRef();
2315   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2316   return ret;
2317 }
2318
2319 /*!
2320  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2321  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2322  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2323  */
2324 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2325 {
2326   checkFullyDefined();
2327   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2328   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2329   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2330   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2331   //
2332   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2333   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2334   //
2335   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2336   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2337   const int *revDescPtr=revDesc->getConstPointer();
2338   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2339   int nbOfCells=getNumberOfCells();
2340   std::vector<bool> ret1(nbOfCells,false);
2341   int sz=0;
2342   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2343     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2344       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2345   //
2346   DataArrayInt *ret2=DataArrayInt::New();
2347   ret2->alloc(sz,1);
2348   int *ret2Ptr=ret2->getPointer();
2349   sz=0;
2350   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2351     if(*it)
2352       *ret2Ptr++=sz;
2353   ret2->setName("BoundaryCells");
2354   return ret2;
2355 }
2356
2357 /*!
2358  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2359  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2360  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2361  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2362  *
2363  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2364  * 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
2365  * equals a cell in \b otherDimM1OnSameCoords.
2366  *
2367  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2368  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2369  *
2370  * \param [in] otherDimM1OnSameCoords
2371  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2372  * \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
2373  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2374  */
2375 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2376 {
2377   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2378     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2379   checkConnectivityFullyDefined();
2380   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2381   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2382     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2383   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2384   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2385   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2386   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2387   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2388   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2389   DataArrayInt *idsOtherInConsti=0;
2390   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2391   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2392   if(!b)
2393     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2394   std::set<int> s1;
2395   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2396     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2397   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2398   s1arr_renum1->sort();
2399   cellIdsRk0=s0arr.retn();
2400   //cellIdsRk1=s_renum1.retn();
2401   cellIdsRk1=s1arr_renum1.retn();
2402 }
2403
2404 /*!
2405  * 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
2406  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2407  * 
2408  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2409  */
2410 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2411 {
2412   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2413   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2414   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2415   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2416   //
2417   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2418   revDesc=0; desc=0; descIndx=0;
2419   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2420   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2421   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2422 }
2423
2424 /*!
2425  * Finds nodes lying on the boundary of \a this mesh.
2426  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2427  *          nodes. The caller is to delete this array using decrRef() as it is no
2428  *          more needed.
2429  *  \throw If the coordinates array is not set.
2430  *  \throw If the nodal connectivity of cells is node defined.
2431  *
2432  *  \if ENABLE_EXAMPLES
2433  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2434  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2435  *  \endif
2436  */
2437 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2438 {
2439   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2440   return skin->computeFetchedNodeIds();
2441 }
2442
2443 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2444 {
2445   incrRef();
2446   return const_cast<MEDCouplingUMesh *>(this);
2447 }
2448
2449 /*!
2450  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2451  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2452  * 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.
2453  * 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.
2454  * 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.
2455  *
2456  * \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
2457  *             parameter is altered during the call.
2458  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2459  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2460  * \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.
2461  *
2462  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2463  */
2464 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2465                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2466 {
2467   typedef MCAuto<DataArrayInt> DAInt;
2468   typedef MCAuto<MEDCouplingUMesh> MCUMesh;
2469
2470   checkFullyDefined();
2471   otherDimM1OnSameCoords.checkFullyDefined();
2472   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2473     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2474   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2475     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2476
2477   // Checking star-shaped M1 group:
2478   DAInt dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2479   MCUMesh meshM2 = otherDimM1OnSameCoords.buildDescendingConnectivity(dt0, dit0, rdt0, rdit0);
2480   DAInt dsi = rdit0->deltaShiftIndex();
2481   DAInt idsTmp0 = dsi->findIdsNotInRange(-1, 3);
2482   if(idsTmp0->getNumberOfTuples())
2483     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group: group is too complex: some points (or edges) have more than two connected segments (or faces)!");
2484   dt0=0; dit0=0; rdt0=0; rdit0=0; idsTmp0=0;
2485
2486   // Get extreme nodes from the group (they won't be duplicated), ie nodes belonging to boundary cells of M1
2487   DAInt xtremIdsM2 = dsi->findIdsEqual(1); dsi = 0;
2488   MCUMesh meshM2Part = static_cast<MEDCouplingUMesh *>(meshM2->buildPartOfMySelf(xtremIdsM2->begin(), xtremIdsM2->end(),true));
2489   DAInt xtrem = meshM2Part->computeFetchedNodeIds();
2490   // Remove from the list points on the boundary of the M0 mesh (those need duplication!)
2491   dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2492   MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;
2493   dsi = rdit0->deltaShiftIndex();
2494   DAInt boundSegs = dsi->findIdsEqual(1);   // boundary segs/faces of the M0 mesh
2495   MCUMesh m0descSkin = static_cast<MEDCouplingUMesh *>(m0desc->buildPartOfMySelf(boundSegs->begin(),boundSegs->end(), true));
2496   DAInt fNodes = m0descSkin->computeFetchedNodeIds();
2497   // In 3D, some points on the boundary of M0 still need duplication:
2498   DAInt notDup = 0;
2499   if (getMeshDimension() == 3)
2500     {
2501       DAInt dnu1=DataArrayInt::New(), dnu2=DataArrayInt::New(), dnu3=DataArrayInt::New(), dnu4=DataArrayInt::New();
2502       MCUMesh m0descSkinDesc = m0descSkin->buildDescendingConnectivity(dnu1, dnu2, dnu3, dnu4);
2503       dnu1=0;dnu2=0;dnu3=0;dnu4=0;
2504       DataArrayInt * corresp=0;
2505       meshM2->areCellsIncludedIn(m0descSkinDesc,2,corresp);
2506       DAInt validIds = corresp->findIdsInRange(0, meshM2->getNumberOfCells());
2507       corresp->decrRef();
2508       if (validIds->getNumberOfTuples())
2509         {
2510           MCUMesh m1IntersecSkin = static_cast<MEDCouplingUMesh *>(m0descSkinDesc->buildPartOfMySelf(validIds->begin(), validIds->end(), true));
2511           DAInt notDuplSkin = m1IntersecSkin->findBoundaryNodes();
2512           DAInt fNodes1 = fNodes->buildSubstraction(notDuplSkin);
2513           notDup = xtrem->buildSubstraction(fNodes1);
2514         }
2515       else
2516         notDup = xtrem->buildSubstraction(fNodes);
2517     }
2518   else
2519     notDup = xtrem->buildSubstraction(fNodes);
2520
2521   // Now compute cells around group (i.e. cells where we will do the propagation to identify the two sub-sets delimited by the group)
2522   DAInt m1Nodes = otherDimM1OnSameCoords.computeFetchedNodeIds();
2523   DAInt dupl = m1Nodes->buildSubstraction(notDup);
2524   DAInt cellsAroundGroup = getCellIdsLyingOnNodes(dupl->begin(), dupl->end(), false);  // false= take cell in, even if not all nodes are in notDup
2525
2526   //
2527   MCUMesh m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true));
2528   int nCells2 = m0Part2->getNumberOfCells();
2529   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2530   MCUMesh m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2531
2532   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2533   DataArrayInt *tmp00=0,*tmp11=0;
2534   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2535   DAInt neighInit00(tmp00);
2536   DAInt neighIInit00(tmp11);
2537   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2538   DataArrayInt *idsTmp=0;
2539   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2540   DAInt ids(idsTmp);
2541   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2542   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2543   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2544   DataArrayInt *tmp0=0,*tmp1=0;
2545   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2546   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2547   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2548   DAInt neigh00(tmp0);
2549   DAInt neighI00(tmp1);
2550
2551   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2552   int seed = 0, nIter = 0;
2553   int nIterMax = nCells2+1; // Safety net for the loop
2554   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2555   hitCells->fillWithValue(-1);
2556   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2557   cellsToModifyConn0_torenum->alloc(0,1);
2558   while (nIter < nIterMax)
2559     {
2560       DAInt t = hitCells->findIdsEqual(-1);
2561       if (!t->getNumberOfTuples())
2562         break;
2563       // Connex zone without the crack (to compute the next seed really)
2564       int dnu;
2565       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2566       int cnt = 0;
2567       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2568         hitCells->setIJ(*ptr,0,1);
2569       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2570       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2571       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2572       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2573       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2574       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2575       DAInt intersec = nonHitCells->buildIntersection(comple);
2576       if (intersec->getNumberOfTuples())
2577         { seed = intersec->getIJ(0,0); }
2578       else
2579         { break; }
2580       nIter++;
2581     }
2582   if (nIter >= nIterMax)
2583     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2584
2585   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2586   cellsToModifyConn0_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2587   cellsToModifyConn1_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2588   //
2589   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2590   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2591   nodeIdsToDuplicate=dupl.retn();
2592 }
2593
2594 /*!
2595  * This method operates a modification of the connectivity and coords in \b this.
2596  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2597  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2598  * 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
2599  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2600  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2601  * 
2602  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2603  * 
2604  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2605  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2606  */
2607 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2608 {
2609   int nbOfNodes=getNumberOfNodes();
2610   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2611   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2612 }
2613
2614 /*!
2615  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2616  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2617  *
2618  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2619  *
2620  * \sa renumberNodesInConn
2621  */
2622 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2623 {
2624   checkConnectivityFullyDefined();
2625   int *conn(getNodalConnectivity()->getPointer());
2626   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2627   int nbOfCells(getNumberOfCells());
2628   for(int i=0;i<nbOfCells;i++)
2629     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2630       {
2631         int& node=conn[iconn];
2632         if(node>=0)//avoid polyhedron separator
2633           {
2634             node+=offset;
2635           }
2636       }
2637   _nodal_connec->declareAsNew();
2638   updateTime();
2639 }
2640
2641 /*!
2642  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2643  *  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
2644  *  of a big mesh.
2645  */
2646 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2647 {
2648   checkConnectivityFullyDefined();
2649   int *conn(getNodalConnectivity()->getPointer());
2650   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2651   int nbOfCells(getNumberOfCells());
2652   for(int i=0;i<nbOfCells;i++)
2653     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2654       {
2655         int& node=conn[iconn];
2656         if(node>=0)//avoid polyhedron separator
2657           {
2658             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2659             if(it!=newNodeNumbersO2N.end())
2660               {
2661                 node=(*it).second;
2662               }
2663             else
2664               {
2665                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2666                 throw INTERP_KERNEL::Exception(oss.str());
2667               }
2668           }
2669       }
2670   _nodal_connec->declareAsNew();
2671   updateTime();
2672 }
2673
2674 /*!
2675  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2676  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2677  * This method is a generalization of shiftNodeNumbersInConn().
2678  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2679  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2680  *         this->getNumberOfNodes(), in "Old to New" mode. 
2681  *         See \ref numbering for more info on renumbering modes.
2682  *  \throw If the nodal connectivity of cells is not defined.
2683  *
2684  *  \if ENABLE_EXAMPLES
2685  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2686  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2687  *  \endif
2688  */
2689 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2690 {
2691   checkConnectivityFullyDefined();
2692   int *conn=getNodalConnectivity()->getPointer();
2693   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2694   int nbOfCells(getNumberOfCells());
2695   for(int i=0;i<nbOfCells;i++)
2696     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2697       {
2698         int& node=conn[iconn];
2699         if(node>=0)//avoid polyhedron separator
2700           {
2701             node=newNodeNumbersO2N[node];
2702           }
2703       }
2704   _nodal_connec->declareAsNew();
2705   updateTime();
2706 }
2707
2708 /*!
2709  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2710  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2711  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2712  * 
2713  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2714  */
2715 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2716 {
2717   checkConnectivityFullyDefined();
2718   int *conn=getNodalConnectivity()->getPointer();
2719   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2720   int nbOfCells=getNumberOfCells();
2721   for(int i=0;i<nbOfCells;i++)
2722     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2723       {
2724         int& node=conn[iconn];
2725         if(node>=0)//avoid polyhedron separator
2726           {
2727             node+=delta;
2728           }
2729       }
2730   _nodal_connec->declareAsNew();
2731   updateTime();
2732 }
2733
2734 /*!
2735  * This method operates a modification of the connectivity in \b this.
2736  * 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.
2737  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2738  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2739  * 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
2740  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2741  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2742  * 
2743  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2744  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2745  * 
2746  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2747  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2748  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2749  */
2750 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2751 {
2752   checkConnectivityFullyDefined();
2753   std::map<int,int> m;
2754   int val=offset;
2755   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2756     m[*work]=val;
2757   int *conn=getNodalConnectivity()->getPointer();
2758   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2759   int nbOfCells=getNumberOfCells();
2760   for(int i=0;i<nbOfCells;i++)
2761     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2762       {
2763         int& node=conn[iconn];
2764         if(node>=0)//avoid polyhedron separator
2765           {
2766             std::map<int,int>::iterator it=m.find(node);
2767             if(it!=m.end())
2768               node=(*it).second;
2769           }
2770       }
2771   updateTime();
2772 }
2773
2774 /*!
2775  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2776  *
2777  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2778  * After the call of this method the number of cells remains the same as before.
2779  *
2780  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2781  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2782  * be strictly in [0;this->getNumberOfCells()).
2783  *
2784  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2785  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2786  * should be contained in[0;this->getNumberOfCells()).
2787  * 
2788  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2789  * \param check
2790  */
2791 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2792 {
2793   checkConnectivityFullyDefined();
2794   int nbCells=getNumberOfCells();
2795   const int *array=old2NewBg;
2796   if(check)
2797     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2798   //
2799   const int *conn=_nodal_connec->getConstPointer();
2800   const int *connI=_nodal_connec_index->getConstPointer();
2801   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2802   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2803   const int *n2oPtr=n2o->begin();
2804   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2805   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2806   newConn->copyStringInfoFrom(*_nodal_connec);
2807   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2808   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2809   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2810   //
2811   int *newC=newConn->getPointer();
2812   int *newCI=newConnI->getPointer();
2813   int loc=0;
2814   newCI[0]=loc;
2815   for(int i=0;i<nbCells;i++)
2816     {
2817       int pos=n2oPtr[i];
2818       int nbOfElts=connI[pos+1]-connI[pos];
2819       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2820       loc+=nbOfElts;
2821       newCI[i+1]=loc;
2822     }
2823   //
2824   setConnectivity(newConn,newConnI);
2825   if(check)
2826     free(const_cast<int *>(array));
2827 }
2828
2829 /*!
2830  * Finds cells whose bounding boxes intersect a given bounding box.
2831  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2832  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2833  *         zMax (if in 3D). 
2834  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2835  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2836  *         extent of the bounding box of cell to produce an addition to this bounding box.
2837  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2838  *         cells. The caller is to delete this array using decrRef() as it is no more
2839  *         needed. 
2840  *  \throw If the coordinates array is not set.
2841  *  \throw If the nodal connectivity of cells is not defined.
2842  *
2843  *  \if ENABLE_EXAMPLES
2844  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2845  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2846  *  \endif
2847  */
2848 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2849 {
2850   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2851   if(getMeshDimension()==-1)
2852     {
2853       elems->pushBackSilent(0);
2854       return elems.retn();
2855     }
2856   int dim=getSpaceDimension();
2857   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2858   const int* conn      = getNodalConnectivity()->getConstPointer();
2859   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2860   const double* coords = getCoords()->getConstPointer();
2861   int nbOfCells=getNumberOfCells();
2862   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2863     {
2864       for (int i=0; i<dim; i++)
2865         {
2866           elem_bb[i*2]=std::numeric_limits<double>::max();
2867           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2868         }
2869
2870       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2871         {
2872           int node= conn[inode];
2873           if(node>=0)//avoid polyhedron separator
2874             {
2875               for (int idim=0; idim<dim; idim++)
2876                 {
2877                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2878                     {
2879                       elem_bb[idim*2] = coords[node*dim+idim] ;
2880                     }
2881                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2882                     {
2883                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2884                     }
2885                 }
2886             }
2887         }
2888       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2889         elems->pushBackSilent(ielem);
2890     }
2891   return elems.retn();
2892 }
2893
2894 /*!
2895  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2896  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2897  * added in 'elems' parameter.
2898  */
2899 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2900 {
2901   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2902   if(getMeshDimension()==-1)
2903     {
2904       elems->pushBackSilent(0);
2905       return elems.retn();
2906     }
2907   int dim=getSpaceDimension();
2908   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2909   const int* conn      = getNodalConnectivity()->getConstPointer();
2910   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2911   const double* coords = getCoords()->getConstPointer();
2912   int nbOfCells=getNumberOfCells();
2913   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2914     {
2915       for (int i=0; i<dim; i++)
2916         {
2917           elem_bb[i*2]=std::numeric_limits<double>::max();
2918           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2919         }
2920
2921       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2922         {
2923           int node= conn[inode];
2924           if(node>=0)//avoid polyhedron separator
2925             {
2926               for (int idim=0; idim<dim; idim++)
2927                 {
2928                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2929                     {
2930                       elem_bb[idim*2] = coords[node*dim+idim] ;
2931                     }
2932                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2933                     {
2934                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2935                     }
2936                 }
2937             }
2938         }
2939       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2940         elems->pushBackSilent(ielem);
2941     }
2942   return elems.retn();
2943 }
2944
2945 /*!
2946  * Returns a type of a cell by its id.
2947  *  \param [in] cellId - the id of the cell of interest.
2948  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2949  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2950  */
2951 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2952 {
2953   const int *ptI=_nodal_connec_index->getConstPointer();
2954   const int *pt=_nodal_connec->getConstPointer();
2955   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2956     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2957   else
2958     {
2959       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2960       throw INTERP_KERNEL::Exception(oss.str());
2961     }
2962 }
2963
2964 /*!
2965  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2966  * This method does not throw exception if geometric type \a type is not in \a this.
2967  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2968  * The coordinates array is not considered here.
2969  *
2970  * \param [in] type the geometric type
2971  * \return cell ids in this having geometric type \a type.
2972  */
2973 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2974 {
2975
2976   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2977   ret->alloc(0,1);
2978   checkConnectivityFullyDefined();
2979   int nbCells=getNumberOfCells();
2980   int mdim=getMeshDimension();
2981   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2982   if(mdim!=(int)cm.getDimension())
2983     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2984   const int *ptI=_nodal_connec_index->getConstPointer();
2985   const int *pt=_nodal_connec->getConstPointer();
2986   for(int i=0;i<nbCells;i++)
2987     {
2988       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2989         ret->pushBackSilent(i);
2990     }
2991   return ret.retn();
2992 }
2993
2994 /*!
2995  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2996  */
2997 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2998 {
2999   const int *ptI=_nodal_connec_index->getConstPointer();
3000   const int *pt=_nodal_connec->getConstPointer();
3001   int nbOfCells=getNumberOfCells();
3002   int ret=0;
3003   for(int i=0;i<nbOfCells;i++)
3004     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
3005       ret++;
3006   return ret;
3007 }
3008
3009 /*!
3010  * Returns the nodal connectivity of a given cell.
3011  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
3012  * all returned node ids can be used in getCoordinatesOfNode().
3013  *  \param [in] cellId - an id of the cell of interest.
3014  *  \param [in,out] conn - a vector where the node ids are appended. It is not
3015  *         cleared before the appending.
3016  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
3017  */
3018 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
3019 {
3020   const int *ptI=_nodal_connec_index->getConstPointer();
3021   const int *pt=_nodal_connec->getConstPointer();
3022   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
3023     if(*w>=0)
3024       conn.push_back(*w);
3025 }
3026
3027 std::string MEDCouplingUMesh::simpleRepr() const
3028 {
3029   static const char msg0[]="No coordinates specified !";
3030   std::ostringstream ret;
3031   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
3032   ret << "Description of mesh : \"" << getDescription() << "\"\n";
3033   int tmpp1,tmpp2;
3034   double tt=getTime(tmpp1,tmpp2);
3035   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
3036   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
3037   if(_mesh_dim>=-1)
3038     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
3039   else
3040     { ret << " Mesh dimension has not been set or is invalid !"; }
3041   if(_coords!=0)
3042     {
3043       const int spaceDim=getSpaceDimension();
3044       ret << spaceDim << "\nInfo attached on space dimension : ";
3045       for(int i=0;i<spaceDim;i++)
3046         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3047       ret << "\n";
3048     }
3049   else
3050     ret << msg0 << "\n";
3051   ret << "Number of nodes : ";
3052   if(_coords!=0)
3053     ret << getNumberOfNodes() << "\n";
3054   else
3055     ret << msg0 << "\n";
3056   ret << "Number of cells : ";
3057   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3058     ret << getNumberOfCells() << "\n";
3059   else
3060     ret << "No connectivity specified !" << "\n";
3061   ret << "Cell types present : ";
3062   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3063     {
3064       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3065       ret << cm.getRepr() << " ";
3066     }
3067   ret << "\n";
3068   return ret.str();
3069 }
3070
3071 std::string MEDCouplingUMesh::advancedRepr() const
3072 {
3073   std::ostringstream ret;
3074   ret << simpleRepr();
3075   ret << "\nCoordinates array : \n___________________\n\n";
3076   if(_coords)
3077     _coords->reprWithoutNameStream(ret);
3078   else
3079     ret << "No array set !\n";
3080   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3081   reprConnectivityOfThisLL(ret);
3082   return ret.str();
3083 }
3084
3085 /*!
3086  * This method returns a C++ code that is a dump of \a this.
3087  * This method will throw if this is not fully defined.
3088  */
3089 std::string MEDCouplingUMesh::cppRepr() const
3090 {
3091   static const char coordsName[]="coords";
3092   static const char connName[]="conn";
3093   static const char connIName[]="connI";
3094   checkFullyDefined();
3095   std::ostringstream ret; ret << "// coordinates" << std::endl;
3096   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3097   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3098   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3099   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3100   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3101   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3102   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3103   return ret.str();
3104 }
3105
3106 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3107 {
3108   std::ostringstream ret;
3109   reprConnectivityOfThisLL(ret);
3110   return ret.str();
3111 }
3112
3113 /*!
3114  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3115  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3116  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3117  * some algos).
3118  * 
3119  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3120  * 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
3121  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3122  */
3123 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3124 {
3125   int mdim=getMeshDimension();
3126   if(mdim<0)
3127     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3128   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3129   MCAuto<DataArrayInt> tmp1,tmp2;
3130   bool needToCpyCT=true;
3131   if(!_nodal_connec)
3132     {
3133       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3134       needToCpyCT=false;
3135     }
3136   else
3137     {
3138       tmp1=_nodal_connec;
3139       tmp1->incrRef();
3140     }
3141   if(!_nodal_connec_index)
3142     {
3143       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3144       needToCpyCT=false;
3145     }
3146   else
3147     {
3148       tmp2=_nodal_connec_index;
3149       tmp2->incrRef();
3150     }
3151   ret->setConnectivity(tmp1,tmp2,false);
3152   if(needToCpyCT)
3153     ret->_types=_types;
3154   if(!_coords)
3155     {
3156       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3157       ret->setCoords(coords);
3158     }
3159   else
3160     ret->setCoords(_coords);
3161   return ret.retn();
3162 }
3163
3164 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3165 {
3166   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3167     {
3168       int nbOfCells=getNumberOfCells();
3169       const int *c=_nodal_connec->getConstPointer();
3170       const int *ci=_nodal_connec_index->getConstPointer();
3171       for(int i=0;i<nbOfCells;i++)
3172         {
3173           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3174           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3175           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3176           stream << "\n";
3177         }
3178     }
3179   else
3180     stream << "Connectivity not defined !\n";
3181 }
3182
3183 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3184 {
3185   const int *ptI=_nodal_connec_index->getConstPointer();
3186   const int *pt=_nodal_connec->getConstPointer();
3187   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3188     return ptI[cellId+1]-ptI[cellId]-1;
3189   else
3190     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3191 }
3192
3193 /*!
3194  * Returns types of cells of the specified part of \a this mesh.
3195  * This method avoids computing sub-mesh explicitely to get its types.
3196  *  \param [in] begin - an array of cell ids of interest.
3197  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3198  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3199  *         describing the cell types. 
3200  *  \throw If the coordinates array is not set.
3201  *  \throw If the nodal connectivity of cells is not defined.
3202  *  \sa getAllGeoTypes()
3203  */
3204 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3205 {
3206   checkFullyDefined();
3207   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3208   const int *conn=_nodal_connec->getConstPointer();
3209   const int *connIndex=_nodal_connec_index->getConstPointer();
3210   for(const int *w=begin;w!=end;w++)
3211     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3212   return ret;
3213 }
3214
3215 /*!
3216  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3217  * Optionally updates
3218  * a set of types of cells constituting \a this mesh. 
3219  * This method is for advanced users having prepared their connectivity before. For
3220  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3221  *  \param [in] conn - the nodal connectivity array. 
3222  *  \param [in] connIndex - the nodal connectivity index array.
3223  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3224  *         mesh is updated.
3225  */
3226 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3227 {
3228   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3229   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3230   if(isComputingTypes)
3231     computeTypes();
3232   declareAsNew();
3233 }
3234
3235 /*!
3236  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3237  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3238  */
3239 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3240     _nodal_connec(0),_nodal_connec_index(0),
3241     _types(other._types)
3242 {
3243   if(other._nodal_connec)
3244     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCopy);
3245   if(other._nodal_connec_index)
3246     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCopy);
3247 }
3248
3249 MEDCouplingUMesh::~MEDCouplingUMesh()
3250 {
3251   if(_nodal_connec)
3252     _nodal_connec->decrRef();
3253   if(_nodal_connec_index)
3254     _nodal_connec_index->decrRef();
3255 }
3256
3257 /*!
3258  * Recomputes a set of cell types of \a this mesh. For more info see
3259  * \ref MEDCouplingUMeshNodalConnectivity.
3260  */
3261 void MEDCouplingUMesh::computeTypes()
3262 {
3263   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3264 }
3265
3266 /*!
3267  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3268  */
3269 void MEDCouplingUMesh::checkFullyDefined() const
3270 {
3271   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3272     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3273 }
3274
3275 /*!
3276  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3277  */
3278 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3279 {
3280   if(!_nodal_connec_index || !_nodal_connec)
3281     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3282 }
3283
3284 /*!
3285  * Returns a number of cells constituting \a this mesh. 
3286  *  \return int - the number of cells in \a this mesh.
3287  *  \throw If the nodal connectivity of cells is not defined.
3288  */
3289 int MEDCouplingUMesh::getNumberOfCells() const
3290
3291   if(_nodal_connec_index)
3292     return _nodal_connec_index->getNumberOfTuples()-1;
3293   else
3294     if(_mesh_dim==-1)
3295       return 1;
3296     else
3297       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3298 }
3299
3300 /*!
3301  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3302  * mesh. For more info see \ref meshes.
3303  *  \return int - the dimension of \a this mesh.
3304  *  \throw If the mesh dimension is not defined using setMeshDimension().
3305  */
3306 int MEDCouplingUMesh::getMeshDimension() const
3307 {
3308   if(_mesh_dim<-1)
3309     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3310   return _mesh_dim;
3311 }
3312
3313 /*!
3314  * Returns a length of the nodal connectivity array.
3315  * This method is for test reason. Normally the integer returned is not useable by
3316  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3317  *  \return int - the length of the nodal connectivity array.
3318  */
3319 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3320 {
3321   return _nodal_connec->getNbOfElems();
3322 }
3323
3324 /*!
3325  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3326  */
3327 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3328 {
3329   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3330   tinyInfo.push_back(getMeshDimension());
3331   tinyInfo.push_back(getNumberOfCells());
3332   if(_nodal_connec)
3333     tinyInfo.push_back(getNodalConnectivityArrayLen());
3334   else
3335     tinyInfo.push_back(-1);
3336 }
3337
3338 /*!
3339  * First step of unserialization process.
3340  */
3341 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3342 {
3343   return tinyInfo[6]<=0;
3344 }
3345
3346 /*!
3347  * Second step of serialization process.
3348  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3349  * \param a1
3350  * \param a2
3351  * \param littleStrings
3352  */
3353 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3354 {
3355   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3356   if(tinyInfo[5]!=-1)
3357     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3358 }
3359
3360 /*!
3361  * Third and final step of serialization process.
3362  */
3363 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3364 {
3365   MEDCouplingPointSet::serialize(a1,a2);
3366   if(getMeshDimension()>-1)
3367     {
3368       a1=DataArrayInt::New();
3369       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3370       int *ptA1=a1->getPointer();
3371       const int *conn=getNodalConnectivity()->getConstPointer();
3372       const int *index=getNodalConnectivityIndex()->getConstPointer();
3373       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3374       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3375     }
3376   else
3377     a1=0;
3378 }
3379
3380 /*!
3381  * Second and final unserialization process.
3382  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3383  */
3384 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3385 {
3386   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3387   setMeshDimension(tinyInfo[5]);
3388   if(tinyInfo[7]!=-1)
3389     {
3390       // Connectivity
3391       const int *recvBuffer=a1->getConstPointer();
3392       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3393       myConnecIndex->alloc(tinyInfo[6]+1,1);
3394       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3395       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3396       myConnec->alloc(tinyInfo[7],1);
3397       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3398       setConnectivity(myConnec, myConnecIndex);
3399     }
3400 }
3401
3402 /*!
3403  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelfSlice.
3404  * CellIds are given using range specified by a start an end and step.
3405  */
3406 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice(int start, int end, int step) const
3407 {
3408   checkFullyDefined();
3409   int ncell=getNumberOfCells();
3410   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3411   ret->_mesh_dim=_mesh_dim;
3412   ret->setCoords(_coords);
3413   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : ");
3414   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3415   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3416   int work=start;
3417   const int *conn=_nodal_connec->getConstPointer();
3418   const int *connIndex=_nodal_connec_index->getConstPointer();
3419   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3420     {
3421       if(work>=0 && work<ncell)
3422         {
3423           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3424         }
3425       else
3426         {
3427           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3428           throw INTERP_KERNEL::Exception(oss.str());
3429         }
3430     }
3431   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3432   int *newConnPtr=newConn->getPointer();
3433   std::set<INTERP_KERNEL::NormalizedCellType> types;
3434   work=start;
3435   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3436     {
3437       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3438       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3439     }
3440   ret->setConnectivity(newConn,newConnI,false);
3441   ret->_types=types;
3442   ret->copyTinyInfoFrom(this);
3443   return ret.retn();
3444 }
3445
3446 /*!
3447  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3448  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3449  * The return newly allocated mesh will share the same coordinates as \a this.
3450  */
3451 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3452 {
3453   checkConnectivityFullyDefined();
3454   int ncell=getNumberOfCells();
3455   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3456   ret->_mesh_dim=_mesh_dim;
3457   ret->setCoords(_coords);
3458   std::size_t nbOfElemsRet=std::distance(begin,end);
3459   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3460   connIndexRet[0]=0;
3461   const int *conn=_nodal_connec->getConstPointer();
3462   const int *connIndex=_nodal_connec_index->getConstPointer();
3463   int newNbring=0;
3464   for(const int *work=begin;work!=end;work++,newNbring++)
3465     {
3466       if(*work>=0 && *work<ncell)
3467         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3468       else
3469         {
3470           free(connIndexRet);
3471           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3472           throw INTERP_KERNEL::Exception(oss.str());
3473         }
3474     }
3475   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3476   int *connRetWork=connRet;
3477   std::set<INTERP_KERNEL::NormalizedCellType> types;
3478   for(const int *work=begin;work!=end;work++)
3479     {
3480       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3481       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3482     }
3483   MCAuto<DataArrayInt> connRetArr=DataArrayInt::New();
3484   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3485   MCAuto<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3486   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3487   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3488   ret->_types=types;
3489   ret->copyTinyInfoFrom(this);
3490   return ret.retn();
3491 }
3492
3493 /*!
3494  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3495  * mesh.<br>
3496  * For 1D cells, the returned field contains lengths.<br>
3497  * For 2D cells, the returned field contains areas.<br>
3498  * For 3D cells, the returned field contains volumes.
3499  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3500  *         orientation, i.e. the volume is always positive.
3501  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3502  *         and one time . The caller is to delete this field using decrRef() as it is no
3503  *         more needed.
3504  */
3505 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3506 {
3507   std::string name="MeasureOfMesh_";
3508   name+=getName();
3509   int nbelem=getNumberOfCells();
3510   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3511   field->setName(name);
3512   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3513   array->alloc(nbelem,1);
3514   double *area_vol=array->getPointer();
3515   field->setArray(array) ; array=0;
3516   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3517   field->synchronizeTimeWithMesh();
3518   if(getMeshDimension()!=-1)
3519     {
3520       int ipt;
3521       INTERP_KERNEL::NormalizedCellType type;
3522       int dim_space=getSpaceDimension();
3523       const double *coords=getCoords()->getConstPointer();
3524       const int *connec=getNodalConnectivity()->getConstPointer();
3525       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3526       for(int iel=0;iel<nbelem;iel++)
3527         {
3528           ipt=connec_index[iel];
3529           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3530           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);
3531         }
3532       if(isAbs)
3533         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3534     }
3535   else
3536     {
3537       area_vol[0]=std::numeric_limits<double>::max();
3538     }
3539   return field.retn();
3540 }
3541
3542 /*!
3543  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3544  * mesh.<br>
3545  * For 1D cells, the returned array contains lengths.<br>
3546  * For 2D cells, the returned array contains areas.<br>
3547  * For 3D cells, the returned array contains volumes.
3548  * This method avoids building explicitly a part of \a this mesh to perform the work.
3549  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3550  *         orientation, i.e. the volume is always positive.
3551  *  \param [in] begin - an array of cell ids of interest.
3552  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3553  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3554  *          delete this array using decrRef() as it is no more needed.
3555  * 
3556  *  \if ENABLE_EXAMPLES
3557  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3558  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3559  *  \endif
3560  *  \sa getMeasureField()
3561  */
3562 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3563 {
3564   std::string name="PartMeasureOfMesh_";
3565   name+=getName();
3566   int nbelem=(int)std::distance(begin,end);
3567   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3568   array->setName(name);
3569   array->alloc(nbelem,1);
3570   double *area_vol=array->getPointer();
3571   if(getMeshDimension()!=-1)
3572     {
3573       int ipt;
3574       INTERP_KERNEL::NormalizedCellType type;
3575       int dim_space=getSpaceDimension();
3576       const double *coords=getCoords()->getConstPointer();
3577       const int *connec=getNodalConnectivity()->getConstPointer();
3578       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3579       for(const int *iel=begin;iel!=end;iel++)
3580         {
3581           ipt=connec_index[*iel];
3582           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3583           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3584         }
3585       if(isAbs)
3586         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3587     }
3588   else
3589     {
3590       area_vol[0]=std::numeric_limits<double>::max();
3591     }
3592   return array.retn();
3593 }
3594
3595 /*!
3596  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3597  * \a this one. The returned field contains the dual cell volume for each corresponding
3598  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3599  *  the dual mesh in P1 sens of \a this.<br>
3600  * For 1D cells, the returned field contains lengths.<br>
3601  * For 2D cells, the returned field contains areas.<br>
3602  * For 3D cells, the returned field contains volumes.
3603  * This method is useful to check "P1*" conservative interpolators.
3604  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3605  *         orientation, i.e. the volume is always positive.
3606  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3607  *          nodes and one time. The caller is to delete this array using decrRef() as
3608  *          it is no more needed.
3609  */
3610 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3611 {
3612   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3613   std::string name="MeasureOnNodeOfMesh_";
3614   name+=getName();
3615   int nbNodes=getNumberOfNodes();
3616   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3617   double cst=1./((double)getMeshDimension()+1.);
3618   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3619   array->alloc(nbNodes,1);
3620   double *valsToFill=array->getPointer();
3621   std::fill(valsToFill,valsToFill+nbNodes,0.);
3622   const double *values=tmp->getArray()->getConstPointer();
3623   MCAuto<DataArrayInt> da=DataArrayInt::New();
3624   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3625   getReverseNodalConnectivity(da,daInd);
3626   const int *daPtr=da->getConstPointer();
3627   const int *daIPtr=daInd->getConstPointer();
3628   for(int i=0;i<nbNodes;i++)
3629     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3630       valsToFill[i]+=cst*values[*cell];
3631   ret->setMesh(this);
3632   ret->setArray(array);
3633   return ret.retn();
3634 }
3635
3636 /*!
3637  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3638  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3639  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3640  * and are normalized.
3641  * <br> \a this can be either 
3642  * - a  2D mesh in 2D or 3D space or 
3643  * - an 1D mesh in 2D space.
3644  * 
3645  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3646  *          cells and one time. The caller is to delete this field using decrRef() as
3647  *          it is no more needed.
3648  *  \throw If the nodal connectivity of cells is not defined.
3649  *  \throw If the coordinates array is not set.
3650  *  \throw If the mesh dimension is not set.
3651  *  \throw If the mesh and space dimension is not as specified above.
3652  */
3653 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3654 {
3655   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3656     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3657   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3658   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3659   int nbOfCells=getNumberOfCells();
3660   int nbComp=getMeshDimension()+1;
3661   array->alloc(nbOfCells,nbComp);
3662   double *vals=array->getPointer();
3663   const int *connI=_nodal_connec_index->getConstPointer();
3664   const int *conn=_nodal_connec->getConstPointer();
3665   const double *coords=_coords->getConstPointer();
3666   if(getMeshDimension()==2)
3667     {
3668       if(getSpaceDimension()==3)
3669         {
3670           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3671           const double *locPtr=loc->getConstPointer();
3672           for(int i=0;i<nbOfCells;i++,vals+=3)
3673             {
3674               int offset=connI[i];
3675               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3676               double n=INTERP_KERNEL::norm<3>(vals);
3677               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3678             }
3679         }
3680       else
3681         {
3682           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3683           const double *isAbsPtr=isAbs->getArray()->begin();
3684           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3685             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3686         }
3687     }
3688   else//meshdimension==1
3689     {
3690       double tmp[2];
3691       for(int i=0;i<nbOfCells;i++)
3692         {
3693           int offset=connI[i];
3694           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3695           double n=INTERP_KERNEL::norm<2>(tmp);
3696           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3697           *vals++=-tmp[1];
3698           *vals++=tmp[0];
3699         }
3700     }
3701   ret->setArray(array);
3702   ret->setMesh(this);
3703   ret->synchronizeTimeWithSupport();
3704   return ret.retn();
3705 }
3706
3707 /*!
3708  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3709  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3710  * and are normalized.
3711  * <br> \a this can be either 
3712  * - a  2D mesh in 2D or 3D space or 
3713  * - an 1D mesh in 2D space.
3714  * 
3715  * This method avoids building explicitly a part of \a this mesh to perform the work.
3716  *  \param [in] begin - an array of cell ids of interest.
3717  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3718  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3719  *          cells and one time. The caller is to delete this field using decrRef() as
3720  *          it is no more needed.
3721  *  \throw If the nodal connectivity of cells is not defined.
3722  *  \throw If the coordinates array is not set.
3723  *  \throw If the mesh dimension is not set.
3724  *  \throw If the mesh and space dimension is not as specified above.
3725  *  \sa buildOrthogonalField()
3726  *
3727  *  \if ENABLE_EXAMPLES
3728  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3729  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3730  *  \endif
3731  */
3732 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3733 {
3734   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3735     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3736   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3737   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3738   std::size_t nbelems=std::distance(begin,end);
3739   int nbComp=getMeshDimension()+1;
3740   array->alloc((int)nbelems,nbComp);
3741   double *vals=array->getPointer();
3742   const int *connI=_nodal_connec_index->getConstPointer();
3743   const int *conn=_nodal_connec->getConstPointer();
3744   const double *coords=_coords->getConstPointer();
3745   if(getMeshDimension()==2)
3746     {
3747       if(getSpaceDimension()==3)
3748         {
3749           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3750           const double *locPtr=loc->getConstPointer();
3751           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3752             {
3753               int offset=connI[*i];
3754               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3755               double n=INTERP_KERNEL::norm<3>(vals);
3756               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3757             }
3758         }
3759       else
3760         {
3761           for(std::size_t i=0;i<nbelems;i++)
3762             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3763         }
3764     }
3765   else//meshdimension==1
3766     {
3767       double tmp[2];
3768       for(const int *i=begin;i!=end;i++)
3769         {
3770           int offset=connI[*i];
3771           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3772           double n=INTERP_KERNEL::norm<2>(tmp);
3773           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3774           *vals++=-tmp[1];
3775           *vals++=tmp[0];
3776         }
3777     }
3778   ret->setArray(array);
3779   ret->setMesh(this);
3780   ret->synchronizeTimeWithSupport();
3781   return ret.retn();
3782 }
3783
3784 /*!
3785  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3786  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3787  * and are \b not normalized.
3788  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3789  *          cells and one time. The caller is to delete this field using decrRef() as
3790  *          it is no more needed.
3791  *  \throw If the nodal connectivity of cells is not defined.
3792  *  \throw If the coordinates array is not set.
3793  *  \throw If \a this->getMeshDimension() != 1.
3794  *  \throw If \a this mesh includes cells of type other than SEG2.
3795  */
3796 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3797 {
3798   if(getMeshDimension()!=1)
3799     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3800   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3801     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3802   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3803   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3804   int nbOfCells=getNumberOfCells();
3805   int spaceDim=getSpaceDimension();
3806   array->alloc(nbOfCells,spaceDim);
3807   double *pt=array->getPointer();
3808   const double *coo=getCoords()->getConstPointer();
3809   std::vector<int> conn;
3810   conn.reserve(2);
3811   for(int i=0;i<nbOfCells;i++)
3812     {
3813       conn.resize(0);
3814       getNodeIdsOfCell(i,conn);
3815       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3816     }
3817   ret->setArray(array);
3818   ret->setMesh(this);
3819   ret->synchronizeTimeWithSupport();
3820   return ret.retn();
3821 }
3822
3823 /*!
3824  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3825  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3826  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3827  * from. If a result face is shared by two 3D cells, then the face in included twice in
3828  * the result mesh.
3829  *  \param [in] origin - 3 components of a point defining location of the plane.
3830  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3831  *         must be greater than 1e-6.
3832  *  \param [in] eps - half-thickness of the plane.
3833  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3834  *         producing correspondent 2D cells. The caller is to delete this array
3835  *         using decrRef() as it is no more needed.
3836  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3837  *         not share the node coordinates array with \a this mesh. The caller is to
3838  *         delete this mesh using decrRef() as it is no more needed.  
3839  *  \throw If the coordinates array is not set.
3840  *  \throw If the nodal connectivity of cells is not defined.
3841  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3842  *  \throw If magnitude of \a vec is less than 1e-6.
3843  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3844  *  \throw If \a this includes quadratic cells.
3845  */
3846 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3847 {
3848   checkFullyDefined();
3849   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3850     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3851   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3852   if(candidates->empty())
3853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3854   std::vector<int> nodes;
3855   DataArrayInt *cellIds1D=0;
3856   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3857   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3858   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3859   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3860   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3861   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3862   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3863   revDesc2=0; revDescIndx2=0;
3864   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3865   revDesc1=0; revDescIndx1=0;
3866   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3867   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3868   //
3869   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3870   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3871     cut3DCurve[*it]=-1;
3872   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3873   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3874   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3875                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3876                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3877   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3878   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3879   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3880   if(cellIds2->empty())
3881     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3882   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3883   ret->setCoords(mDesc1->getCoords());
3884   ret->setConnectivity(conn,connI,true);
3885   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3886   return ret.retn();
3887 }
3888
3889 /*!
3890  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3891 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
3892 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3893 the result mesh.
3894  *  \param [in] origin - 3 components of a point defining location of the plane.
3895  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3896  *         must be greater than 1e-6.
3897  *  \param [in] eps - half-thickness of the plane.
3898  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3899  *         producing correspondent segments. The caller is to delete this array
3900  *         using decrRef() as it is no more needed.
3901  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3902  *         mesh in 3D space. This mesh does not share the node coordinates array with
3903  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3904  *         no more needed. 
3905  *  \throw If the coordinates array is not set.
3906  *  \throw If the nodal connectivity of cells is not defined.
3907  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3908  *  \throw If magnitude of \a vec is less than 1e-6.
3909  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3910  *  \throw If \a this includes quadratic cells.
3911  */
3912 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3913 {
3914   checkFullyDefined();
3915   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3916     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3917   MCAuto<DataArrayInt> candidates(getCellIdsCrossingPlane(origin,vec,eps));
3918   if(candidates->empty())
3919     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3920   std::vector<int> nodes;
3921   DataArrayInt *cellIds1D(0);
3922   MCAuto<MEDCouplingUMesh> subMesh(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3923   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3924   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
3925   MCAuto<MEDCouplingUMesh> mDesc1(subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3926   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3927   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3928   //
3929   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3930   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3931     cut3DCurve[*it]=-1;
3932   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3933   int ncellsSub=subMesh->getNumberOfCells();
3934   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3935   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3936                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3937                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3938   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3939   conn->alloc(0,1);
3940   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3941   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3942   for(int i=0;i<ncellsSub;i++)
3943     {
3944       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3945         {
3946           if(cut3DSurf[i].first!=-2)
3947             {
3948               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3949               connI->pushBackSilent(conn->getNumberOfTuples());
3950               cellIds2->pushBackSilent(i);
3951             }
3952           else
3953             {
3954               int cellId3DSurf=cut3DSurf[i].second;
3955               int offset=nodalI[cellId3DSurf]+1;
3956               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3957               for(int j=0;j<nbOfEdges;j++)
3958                 {
3959                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3960                   connI->pushBackSilent(conn->getNumberOfTuples());
3961                   cellIds2->pushBackSilent(cellId3DSurf);
3962                 }
3963             }
3964         }
3965     }
3966   if(cellIds2->empty())
3967     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3968   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3969   ret->setCoords(mDesc1->getCoords());
3970   ret->setConnectivity(conn,connI,true);
3971   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3972   return ret.retn();
3973 }
3974
3975 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::clipSingle3DCellByPlane(const double origin[3], const double vec[3], double eps) const
3976 {
3977   checkFullyDefined();
3978   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3979     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3980   if(getNumberOfCells()!=1)
3981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works only on mesh containing exactly one cell !");
3982   //
3983   std::vector<int> nodes;
3984   findNodesOnPlane(origin,vec,eps,nodes);
3985   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),desc2(DataArrayInt::New()),descIndx1(DataArrayInt::New()),descIndx2(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDesc2(DataArrayInt::New()),revDescIndx1(DataArrayInt::New()),revDescIndx2(DataArrayInt::New());
3986   MCAuto<MEDCouplingUMesh> mDesc2(buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2));//meshDim==2 spaceDim==3
3987   revDesc2=0; revDescIndx2=0;
3988   MCAuto<MEDCouplingUMesh> mDesc1(mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3989   revDesc1=0; revDescIndx1=0;
3990   DataArrayInt *cellIds1D(0);
3991   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3992   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3993   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3994   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3995     cut3DCurve[*it]=-1;
3996   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3997   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3998   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->begin(),mDesc2->getNodalConnectivityIndex()->begin(),
3999                               mDesc1->getNodalConnectivity()->begin(),mDesc1->getNodalConnectivityIndex()->begin(),
4000                               desc1->begin(),descIndx1->begin(),cut3DSurf);
4001   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New());
4002   connI->pushBackSilent(0); conn->alloc(0,1);
4003   {
4004     MCAuto<DataArrayInt> cellIds2(DataArrayInt::New()); cellIds2->alloc(0,1);
4005     assemblyForSplitFrom3DSurf(cut3DSurf,desc2->begin(),descIndx2->begin(),conn,connI,cellIds2);
4006     if(cellIds2->empty())
4007       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
4008   }
4009   std::vector<std::vector<int> > res;
4010   buildSubCellsFromCut(cut3DSurf,desc2->begin(),descIndx2->begin(),mDesc1->getCoords()->begin(),eps,res);
4011   std::size_t sz(res.size());
4012   if(res.size()==mDesc1->getNumberOfCells())
4013     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane : cell is not clipped !");
4014   for(std::size_t i=0;i<sz;i++)
4015     {
4016       conn->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
4017       conn->insertAtTheEnd(res[i].begin(),res[i].end());
4018       connI->pushBackSilent(conn->getNumberOfTuples());
4019     }
4020   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
4021   ret->setCoords(mDesc1->getCoords());
4022   ret->setConnectivity(conn,connI,true);
4023   int nbCellsRet(ret->getNumberOfCells());
4024   //
4025   MCAuto<DataArrayDouble> vec2(DataArrayDouble::New()); vec2->alloc(1,3); std::copy(vec,vec+3,vec2->getPointer());
4026   MCAuto<MEDCouplingFieldDouble> ortho(ret->buildOrthogonalField());
4027   MCAuto<DataArrayDouble> ortho2(ortho->getArray()->selectByTupleIdSafeSlice(0,1,1));
4028   MCAuto<DataArrayDouble> dott(DataArrayDouble::Dot(ortho2,vec2));
4029   MCAuto<DataArrayDouble> ccm(ret->computeCellCenterOfMass());
4030   MCAuto<DataArrayDouble> occm;
4031   {
4032     MCAuto<DataArrayDouble> pt(DataArrayDouble::New()); pt->alloc(1,3); std::copy(origin,origin+3,pt->getPointer());
4033     occm=DataArrayDouble::Substract(ccm,pt);
4034   }
4035   vec2=DataArrayDouble::New(); vec2->alloc(nbCellsRet,3);
4036   vec2->setPartOfValuesSimple1(vec[0],0,nbCellsRet,1,0,1,1); vec2->setPartOfValuesSimple1(vec[1],0,nbCellsRet,1,1,2,1); vec2->setPartOfValuesSimple1(vec[2],0,nbCellsRet,1,2,3,1);
4037   MCAuto<DataArrayDouble> dott2(DataArrayDouble::Dot(occm,vec2));
4038   //
4039   const int *cPtr(ret->getNodalConnectivity()->begin()),*ciPtr(ret->getNodalConnectivityIndex()->begin());
4040   MCAuto<MEDCouplingUMesh> ret2(MEDCouplingUMesh::New("Clip3D",3));
4041   ret2->setCoords(mDesc1->getCoords());
4042   MCAuto<DataArrayInt> conn2(DataArrayInt::New()),conn2I(DataArrayInt::New());
4043   conn2I->pushBackSilent(0); conn2->alloc(0,1);
4044   std::vector<int> cell0(1,(int)INTERP_KERNEL::NORM_POLYHED);
4045   std::vector<int> cell1(1,(int)INTERP_KERNEL::NORM_POLYHED);
4046   if(dott->getIJ(0,0)>0)
4047     {
4048       cell0.insert(cell0.end(),cPtr+1,cPtr+ciPtr[1]);
4049       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell1,cell1.end()));
4050     }
4051   else
4052     {
4053       cell1.insert(cell1.end(),cPtr+1,cPtr+ciPtr[1]);
4054       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell0,cell0.end()));
4055     }
4056   for(int i=1;i<nbCellsRet;i++)
4057     {
4058       if(dott2->getIJ(i,0)<0)
4059         {
4060           if(ciPtr[i+1]-ciPtr[i]>=4)
4061             {
4062               cell0.push_back(-1);
4063               cell0.insert(cell0.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
4064             }
4065         }
4066       else
4067         {
4068           if(ciPtr[i+1]-ciPtr[i]>=4)
4069             {
4070               cell1.push_back(-1);
4071               cell1.insert(cell1.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
4072             }
4073         }
4074     }
4075   conn2->insertAtTheEnd(cell0.begin(),cell0.end());
4076   conn2I->pushBackSilent(conn2->getNumberOfTuples());
4077   conn2->insertAtTheEnd(cell1.begin(),cell1.end());
4078   conn2I->pushBackSilent(conn2->getNumberOfTuples());
4079   ret2->setConnectivity(conn2,conn2I,true);
4080   ret2->checkConsistencyLight();
4081   ret2->writeVTK("ret2.vtu");
4082   ret2->orientCorrectlyPolyhedrons();
4083   return ret2;
4084 }
4085
4086 /*!
4087  * Finds cells whose bounding boxes intersect a given plane.
4088  *  \param [in] origin - 3 components of a point defining location of the plane.
4089  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
4090  *         must be greater than 1e-6.
4091  *  \param [in] eps - half-thickness of the plane.
4092  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
4093  *         cells. The caller is to delete this array using decrRef() as it is no more
4094  *         needed.
4095  *  \throw If the coordinates array is not set.
4096  *  \throw If the nodal connectivity of cells is not defined.
4097  *  \throw If \a this->getSpaceDimension() != 3.
4098  *  \throw If magnitude of \a vec is less than 1e-6.
4099  *  \sa buildSlice3D()
4100  */
4101 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
4102 {
4103   checkFullyDefined();
4104   if(getSpaceDimension()!=3)
4105     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
4106   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4107   if(normm<1e-6)
4108     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4109   double vec2[3];
4110   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
4111   double angle=acos(vec[2]/normm);
4112   MCAuto<DataArrayInt> cellIds;
4113   double bbox[6];
4114   if(angle>eps)
4115     {
4116       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
4117       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
4118       if(normm2/normm>1e-6)
4119         DataArrayDouble::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer(),coo->getPointer());
4120       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
4121       mw->setCoords(coo);
4122       mw->getBoundingBox(bbox);
4123       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4124       cellIds=mw->getCellsInBoundingBox(bbox,eps);
4125     }
4126   else
4127     {
4128       getBoundingBox(bbox);
4129       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4130       cellIds=getCellsInBoundingBox(bbox,eps);
4131     }
4132   return cellIds.retn();
4133 }
4134
4135 /*!
4136  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
4137  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
4138  * No consideration of coordinate is done by this method.
4139  * 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)
4140  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
4141  */
4142 bool MEDCouplingUMesh::isContiguous1D() const
4143 {
4144   if(getMeshDimension()!=1)
4145     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
4146   int nbCells=getNumberOfCells();
4147   if(nbCells<1)
4148     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
4149   const int *connI(_nodal_connec_index->begin()),*conn(_nodal_connec->begin());
4150   int ref=conn[connI[0]+2];
4151   for(int i=1;i<nbCells;i++)
4152     {
4153       if(conn[connI[i]+1]!=ref)
4154         return false;
4155       ref=conn[connI[i]+2];
4156     }
4157   return true;
4158 }
4159
4160 /*!
4161  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4162  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4163  * \param pt reference point of the line
4164  * \param v normalized director vector of the line
4165  * \param eps max precision before throwing an exception
4166  * \param res output of size this->getNumberOfCells
4167  */
4168 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4169 {
4170   if(getMeshDimension()!=1)
4171     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4172   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4173     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4174   if(getSpaceDimension()!=3)
4175     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4176   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4177   const double *fPtr=f->getArray()->getConstPointer();
4178   double tmp[3];
4179   for(int i=0;i<getNumberOfCells();i++)
4180     {
4181       const double *tmp1=fPtr+3*i;
4182       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4183       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4184       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4185       double n1=INTERP_KERNEL::norm<3>(tmp);
4186       n1/=INTERP_KERNEL::norm<3>(tmp1);
4187       if(n1>eps)
4188         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4189     }
4190   const double *coo=getCoords()->getConstPointer();
4191   for(int i=0;i<getNumberOfNodes();i++)
4192     {
4193       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4194       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4195       res[i]=std::accumulate(tmp,tmp+3,0.);
4196     }
4197 }
4198
4199 /*!
4200  * 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. 
4201  * \a this is expected to be a mesh so that its space dimension is equal to its
4202  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4203  * 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).
4204  *
4205  * 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
4206  * 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).
4207  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4208  *
4209  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4210  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4211  *
4212  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4213  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4214  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4215  * \return the positive value of the distance.
4216  * \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
4217  * dimension - 1.
4218  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4219  */
4220 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4221 {
4222   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4223   if(meshDim!=spaceDim-1)
4224     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4225   if(meshDim!=2 && meshDim!=1)
4226     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4227   checkFullyDefined();
4228   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4229     { 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()); }
4230   DataArrayInt *ret1=0;
4231   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4232   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4233   MCAuto<DataArrayInt> ret1Safe(ret1);
4234   cellId=*ret1Safe->begin();
4235   return *ret0->begin();
4236 }
4237
4238 /*!
4239  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4240  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4241  * 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
4242  * 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).
4243  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4244  * 
4245  * \a this is expected to be a mesh so that its space dimension is equal to its
4246  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4247  * 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).
4248  *
4249  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4250  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4251  *
4252  * \param [in] pts the list of points in which each tuple represents a point
4253  * \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.
4254  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4255  * \throw if number of components of \a pts is not equal to the space dimension.
4256  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4257  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4258  */
4259 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4260 {
4261   if(!pts)
4262     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4263   pts->checkAllocated();
4264   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4265   if(meshDim!=spaceDim-1)
4266     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4267   if(meshDim!=2 && meshDim!=1)
4268     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4269   if(pts->getNumberOfComponents()!=spaceDim)
4270     {
4271       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4272       throw INTERP_KERNEL::Exception(oss.str());
4273     }
4274   checkFullyDefined();
4275   int nbCells=getNumberOfCells();
4276   if(nbCells==0)
4277     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4278   int nbOfPts=pts->getNumberOfTuples();
4279   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4280   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4281   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4282   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4283   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4284   const double *bbox(bboxArr->begin());
4285   switch(spaceDim)
4286   {
4287     case 3:
4288       {
4289         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4290         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4291           {
4292             double x=std::numeric_limits<double>::max();
4293             std::vector<int> elems;
4294             myTree.getMinDistanceOfMax(ptsPtr,x);
4295             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4296             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4297           }
4298         break;
4299       }
4300     case 2:
4301       {
4302         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4303         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4304           {
4305             double x=std::numeric_limits<double>::max();
4306             std::vector<int> elems;
4307             myTree.getMinDistanceOfMax(ptsPtr,x);
4308             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4309             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4310           }
4311         break;
4312       }
4313     default:
4314       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4315   }
4316   cellIds=ret1.retn();
4317   return ret0.retn();
4318 }
4319
4320 /// @cond INTERNAL
4321
4322 /*!
4323  * \param [in] pt the start pointer (included) of the coordinates of the point
4324  * \param [in] cellIdsBg the start pointer (included) of cellIds
4325  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4326  * \param [in] nc nodal connectivity
4327  * \param [in] ncI nodal connectivity index
4328  * \param [in,out] ret0 the min distance between \a this and the external input point
4329  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4330  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4331  */
4332 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)
4333 {
4334   cellId=-1;
4335   ret0=std::numeric_limits<double>::max();
4336   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4337     {
4338       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4339       {
4340         case INTERP_KERNEL::NORM_TRI3:
4341           {
4342             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4343             if(tmp<ret0)
4344               { ret0=tmp; cellId=*zeCell; }
4345             break;
4346           }
4347         case INTERP_KERNEL::NORM_QUAD4:
4348         case INTERP_KERNEL::NORM_POLYGON:
4349           {
4350             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4351             if(tmp<ret0)
4352               { ret0=tmp; cellId=*zeCell; }
4353             break;
4354           }
4355         default:
4356           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4357       }
4358     }
4359 }
4360
4361 /*!
4362  * \param [in] pt the start pointer (included) of the coordinates of the point
4363  * \param [in] cellIdsBg the start pointer (included) of cellIds
4364  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4365  * \param [in] nc nodal connectivity
4366  * \param [in] ncI nodal connectivity index
4367  * \param [in,out] ret0 the min distance between \a this and the external input point
4368  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4369  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4370  */
4371 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)
4372 {
4373   cellId=-1;
4374   ret0=std::numeric_limits<double>::max();
4375   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4376     {
4377       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4378       {
4379         case INTERP_KERNEL::NORM_SEG2:
4380           {
4381             std::size_t uselessEntry=0;
4382             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4383             tmp=sqrt(tmp);
4384             if(tmp<ret0)
4385               { ret0=tmp; cellId=*zeCell; }
4386             break;
4387           }
4388         default:
4389           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4390       }
4391     }
4392 }
4393 /// @endcond
4394
4395 /*!
4396  * Finds cells in contact with a ball (i.e. a point with precision). 
4397  * 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.
4398  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4399  *
4400  * \warning This method is suitable if the caller intends to evaluate only one
4401  *          point, for more points getCellsContainingPoints() is recommended as it is
4402  *          faster. 
4403  *  \param [in] pos - array of coordinates of the ball central point.
4404  *  \param [in] eps - ball radius.
4405  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4406  *         if there are no such cells.
4407  *  \throw If the coordinates array is not set.
4408  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4409  */
4410 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4411 {
4412   std::vector<int> elts;
4413   getCellsContainingPoint(pos,eps,elts);
4414   if(elts.empty())
4415     return -1;
4416   return elts.front();
4417 }
4418
4419 /*!
4420  * Finds cells in contact with a ball (i.e. a point with precision).
4421  * 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.
4422  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4423  * \warning This method is suitable if the caller intends to evaluate only one
4424  *          point, for more points getCellsContainingPoints() is recommended as it is
4425  *          faster. 
4426  *  \param [in] pos - array of coordinates of the ball central point.
4427  *  \param [in] eps - ball radius.
4428  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4429  *         before inserting ids.
4430  *  \throw If the coordinates array is not set.
4431  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4432  *
4433  *  \if ENABLE_EXAMPLES
4434  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4435  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4436  *  \endif
4437  */
4438 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4439 {
4440   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4441   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4442   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4443 }
4444
4445 /// @cond INTERNAL
4446
4447 namespace MEDCoupling
4448 {
4449   template<const int SPACEDIMM>
4450   class DummyClsMCUG
4451   {
4452   public:
4453     static const int MY_SPACEDIM=SPACEDIMM;
4454     static const int MY_MESHDIM=8;
4455     typedef int MyConnType;
4456     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4457     // begin
4458     // useless, but for windows compilation ...
4459     const double* getCoordinatesPtr() const { return 0; }
4460     const int* getConnectivityPtr() const { return 0; }
4461     const int* getConnectivityIndexPtr() const { return 0; }
4462     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4463     // end
4464   };
4465
4466   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MCAuto<INTERP_KERNEL::Node>,int>& m)
4467   {
4468     INTERP_KERNEL::Edge *ret(0);
4469     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]));
4470     m[n0]=bg[0]; m[n1]=bg[1];
4471     switch(typ)
4472     {
4473       case INTERP_KERNEL::NORM_SEG2:
4474         {
4475           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4476           break;
4477         }
4478       case INTERP_KERNEL::NORM_SEG3:
4479         {
4480           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4481           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4482           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4483           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4484           bool colinearity(inters.areColinears());
4485           delete e1; delete e2;
4486           if(colinearity)
4487             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4488           else
4489             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4490           break;
4491         }
4492       default:
4493         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4494     }
4495     return ret;
4496   }
4497
4498   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4499   {
4500     INTERP_KERNEL::Edge *ret=0;
4501     switch(typ)
4502     {
4503       case INTERP_KERNEL::NORM_SEG2:
4504         {
4505           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4506           break;
4507         }
4508       case INTERP_KERNEL::NORM_SEG3:
4509         {
4510           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4511           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4512           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4513           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4514           bool colinearity=inters.areColinears();
4515           delete e1; delete e2;
4516           if(colinearity)
4517             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4518           else
4519             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4520           mapp2[bg[2]].second=false;
4521           break;
4522         }
4523       default:
4524         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4525     }
4526     return ret;
4527   }
4528
4529   /*!
4530    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4531    * the global mesh 'mDesc'.
4532    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4533    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4534    */
4535   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4536                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4537   {
4538     mapp.clear();
4539     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.
4540     const double *coo=mDesc->getCoords()->getConstPointer();
4541     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4542     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4543     std::set<int> s;
4544     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4545       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4546     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4547       {
4548         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4549         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4550       }
4551     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4552     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4553       {
4554         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4555         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4556       }
4557     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4558       {
4559         if((*it2).second.second)
4560           mapp[(*it2).second.first]=(*it2).first;
4561         ((*it2).second.first)->decrRef();
4562       }
4563     return ret;
4564   }
4565
4566   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4567   {
4568     if(nodeId>=offset2)
4569       {
4570         int locId=nodeId-offset2;
4571         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4572       }
4573     if(nodeId>=offset1)
4574       {
4575         int locId=nodeId-offset1;
4576         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4577       }
4578     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4579   }
4580
4581   /**
4582    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4583    */
4584   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4585                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4586                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4587   {
4588     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4589       {
4590         int eltId1=abs(*desc1)-1;
4591         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4592           {
4593             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4594             if(it==mappRev.end())
4595               {
4596                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4597                 mapp[node]=*it1;
4598                 mappRev[*it1]=node;
4599               }
4600           }
4601       }
4602   }
4603 }
4604
4605 /// @endcond
4606
4607 template<int SPACEDIM>
4608 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4609                                                    double eps, MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4610 {
4611   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4612   int *eltsIndexPtr(eltsIndex->getPointer());
4613   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4614   const double *bbox(bboxArr->begin());
4615   int nbOfCells=getNumberOfCells();
4616   const int *conn=_nodal_connec->getConstPointer();
4617   const int *connI=_nodal_connec_index->getConstPointer();
4618   double bb[2*SPACEDIM];
4619   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4620   for(int i=0;i<nbOfPoints;i++)
4621     {
4622       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4623       for(int j=0;j<SPACEDIM;j++)
4624         {
4625           bb[2*j]=pos[SPACEDIM*i+j];
4626           bb[2*j+1]=pos[SPACEDIM*i+j];
4627         }
4628       std::vector<int> candidates;
4629       myTree.getIntersectingElems(bb,candidates);
4630       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4631         {
4632           int sz(connI[(*iter)+1]-connI[*iter]-1);
4633           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4634           bool status(false);
4635           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4636             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4637           else
4638             {
4639               if(SPACEDIM!=2)
4640                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4641               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4642               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4643               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4644               INTERP_KERNEL::QuadraticPolygon *pol(0);
4645               for(int j=0;j<sz;j++)
4646                 {
4647                   int nodeId(conn[connI[*iter]+1+j]);
4648                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4649                 }
4650               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4651                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4652               else
4653                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4654               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4655               double a(0.),b(0.),c(0.);
4656               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4657               status=pol->isInOrOut2(n);
4658               delete pol; n->decrRef();
4659             }
4660           if(status)
4661             {
4662               eltsIndexPtr[i+1]++;
4663               elts->pushBackSilent(*iter);
4664             }
4665         }
4666     }
4667 }
4668 /*!
4669  * Finds cells in contact with several balls (i.e. points with precision).
4670  * This method is an extension of getCellContainingPoint() and
4671  * getCellsContainingPoint() for the case of multiple points.
4672  * 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.
4673  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4674  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4675  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4676  *         this->getSpaceDimension() * \a nbOfPoints 
4677  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4678  *  \param [in] eps - radius of balls (i.e. the precision).
4679  *  \param [out] elts - vector returning ids of found cells.
4680  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4681  *         dividing cell ids in \a elts into groups each referring to one
4682  *         point. Its every element (except the last one) is an index pointing to the
4683  *         first id of a group of cells. For example cells in contact with the *i*-th
4684  *         point are described by following range of indices:
4685  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4686  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4687  *         Number of cells in contact with the *i*-th point is
4688  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4689  *  \throw If the coordinates array is not set.
4690  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4691  *
4692  *  \if ENABLE_EXAMPLES
4693  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4694  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4695  *  \endif
4696  */
4697 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4698                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4699 {
4700   int spaceDim=getSpaceDimension();
4701   int mDim=getMeshDimension();
4702   if(spaceDim==3)
4703     {
4704       if(mDim==3)
4705         {
4706           const double *coords=_coords->getConstPointer();
4707           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4708         }
4709       /*else if(mDim==2)
4710         {
4711
4712         }*/
4713       else
4714         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4715     }
4716   else if(spaceDim==2)
4717     {
4718       if(mDim==2)
4719         {
4720           const double *coords=_coords->getConstPointer();
4721           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4722         }
4723       else
4724         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4725     }
4726   else if(spaceDim==1)
4727     {
4728       if(mDim==1)
4729         {
4730           const double *coords=_coords->getConstPointer();
4731           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4732         }
4733       else
4734         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4735     }
4736   else
4737     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4738 }
4739
4740 /*!
4741  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4742  * least two its edges intersect each other anywhere except their extremities. An
4743  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4744  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4745  *         cleared before filling in.
4746  *  \param [in] eps - precision.
4747  *  \throw If \a this->getMeshDimension() != 2.
4748  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4749  */
4750 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4751 {
4752   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4753   if(getMeshDimension()!=2)
4754     throw INTERP_KERNEL::Exception(msg);
4755   int spaceDim=getSpaceDimension();
4756   if(spaceDim!=2 && spaceDim!=3)
4757     throw INTERP_KERNEL::Exception(msg);
4758   const int *conn=_nodal_connec->getConstPointer();
4759   const int *connI=_nodal_connec_index->getConstPointer();
4760   int nbOfCells=getNumberOfCells();
4761   std::vector<double> cell2DinS2;
4762   for(int i=0;i<nbOfCells;i++)
4763     {
4764       int offset=connI[i];
4765       int nbOfNodesForCell=connI[i+1]-offset-1;
4766       if(nbOfNodesForCell<=3)
4767         continue;
4768       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4769       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4770       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4771         cells.push_back(i);
4772       cell2DinS2.clear();
4773     }
4774 }
4775
4776 /*!
4777  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4778  *
4779  * 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.
4780  * 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.
4781  * 
4782  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4783  * This convex envelop is computed using Jarvis march algorithm.
4784  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4785  * 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)
4786  * 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.
4787  *
4788  * \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.
4789  * \sa MEDCouplingUMesh::colinearize2D
4790  */
4791 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4792 {
4793   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4794     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4795   checkFullyDefined();
4796   const double *coords=getCoords()->getConstPointer();
4797   int nbOfCells=getNumberOfCells();
4798   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4799   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4800   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4801   int *workIndexOut=nodalConnecIndexOut->getPointer();
4802   *workIndexOut=0;
4803   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4804   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4805   std::set<INTERP_KERNEL::NormalizedCellType> types;
4806   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4807   isChanged->alloc(0,1);
4808   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4809     {
4810       int pos=nodalConnecOut->getNumberOfTuples();
4811       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4812         isChanged->pushBackSilent(i);
4813       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4814       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4815     }
4816   if(isChanged->empty())
4817     return 0;
4818   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4819   _types=types;
4820   return isChanged.retn();
4821 }
4822
4823 /*!
4824  * This method is \b NOT const because it can modify \a this.
4825  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4826  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4827  * \param policy specifies the type of extrusion chosen:
4828  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4829  *   will be repeated to build each level
4830  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4831  *   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
4832  *   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
4833  *   arc.
4834  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4835  */
4836 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4837 {
4838   checkFullyDefined();
4839   mesh1D->checkFullyDefined();
4840   if(!mesh1D->isContiguous1D())
4841     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4842   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4843     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4844   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4845     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4846   if(mesh1D->getMeshDimension()!=1)
4847     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4848   bool isQuad=false;
4849   if(isPresenceOfQuadratic())
4850     {
4851       if(mesh1D->isFullyQuadratic())
4852         isQuad=true;
4853       else
4854         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4855     }
4856   int oldNbOfNodes(getNumberOfNodes());
4857   MCAuto<DataArrayDouble> newCoords;
4858   switch(policy)
4859   {
4860     case 0:
4861       {
4862         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4863         break;
4864       }
4865     case 1:
4866       {
4867         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4868         break;
4869       }
4870     default:
4871       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4872   }
4873   setCoords(newCoords);
4874   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4875   updateTime();
4876   return ret.retn();
4877 }
4878
4879 /*!
4880  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4881  * If it is not the case an exception will be thrown.
4882  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4883  * intersection of plane defined by ('origin','vec').
4884  * This method has one in/out parameter : 'cut3DCurve'.
4885  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4886  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4887  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4888  * This method will throw an exception if \a this contains a non linear segment.
4889  */
4890 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4891 {
4892   checkFullyDefined();
4893   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4894     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4895   int ncells=getNumberOfCells();
4896   int nnodes=getNumberOfNodes();
4897   double vec2[3],vec3[3],vec4[3];
4898   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4899   if(normm<1e-6)
4900     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4901   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4902   const int *conn=_nodal_connec->getConstPointer();
4903   const int *connI=_nodal_connec_index->getConstPointer();
4904   const double *coo=_coords->getConstPointer();
4905   std::vector<double> addCoo;
4906   for(int i=0;i<ncells;i++)
4907     {
4908       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4909         {
4910           if(cut3DCurve[i]==-2)
4911             {
4912               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4913               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];
4914               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4915               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4916               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4917                 {
4918                   const double *st2=coo+3*st;
4919                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4920                   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]));
4921                   if(pos>eps && pos<1-eps)
4922                     {
4923                       int nNode=((int)addCoo.size())/3;
4924                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4925                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4926                       cut3DCurve[i]=nnodes+nNode;
4927                     }
4928                 }
4929             }
4930         }
4931       else
4932         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4933     }
4934   if(!addCoo.empty())
4935     {
4936       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4937       MCAuto<DataArrayDouble> coo2=DataArrayDouble::New();
4938       coo2->alloc(newNbOfNodes,3);
4939       double *tmp=coo2->getPointer();
4940       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4941       std::copy(addCoo.begin(),addCoo.end(),tmp);
4942       DataArrayDouble::SetArrayIn(coo2,_coords);
4943     }
4944 }
4945
4946 /*!
4947  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4948  * \param mesh1D is the input 1D mesh used for translation computation.
4949  * \return newCoords new coords filled by this method. 
4950  */
4951 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4952 {
4953   int oldNbOfNodes=getNumberOfNodes();
4954   int nbOf1DCells=mesh1D->getNumberOfCells();
4955   int spaceDim=getSpaceDimension();
4956   DataArrayDouble *ret=DataArrayDouble::New();
4957   std::vector<bool> isQuads;
4958   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4959   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4960   double *retPtr=ret->getPointer();
4961   const double *coords=getCoords()->getConstPointer();
4962   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4963   std::vector<int> v;
4964   std::vector<double> c;
4965   double vec[3];
4966   v.reserve(3);
4967   c.reserve(6);
4968   for(int i=0;i<nbOf1DCells;i++)
4969     {
4970       v.resize(0);
4971       mesh1D->getNodeIdsOfCell(i,v);
4972       c.resize(0);
4973       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4974       mesh1D->getCoordinatesOfNode(v[0],c);
4975       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4976       for(int j=0;j<oldNbOfNodes;j++)
4977         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4978       if(isQuad)
4979         {
4980           c.resize(0);
4981           mesh1D->getCoordinatesOfNode(v[1],c);
4982           mesh1D->getCoordinatesOfNode(v[0],c);
4983           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4984           for(int j=0;j<oldNbOfNodes;j++)
4985             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4986         }
4987     }
4988   ret->copyStringInfoFrom(*getCoords());
4989   return ret;
4990 }
4991
4992 /*!
4993  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4994  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4995  * \return newCoords new coords filled by this method. 
4996  */
4997 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4998 {
4999   if(mesh1D->getSpaceDimension()==2)
5000     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
5001   if(mesh1D->getSpaceDimension()==3)
5002     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
5003   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
5004 }
5005
5006 /*!
5007  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
5008  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
5009  * \return newCoords new coords filled by this method. 
5010  */
5011 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
5012 {
5013   if(isQuad)
5014     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
5015   int oldNbOfNodes=getNumberOfNodes();
5016   int nbOf1DCells=mesh1D->getNumberOfCells();
5017   if(nbOf1DCells<2)
5018     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
5019   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
5020   int nbOfLevsInVec=nbOf1DCells+1;
5021   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
5022   double *retPtr=ret->getPointer();
5023   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
5024   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5025   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
5026   tmp->setCoords(tmp2);
5027   const double *coo1D=mesh1D->getCoords()->getConstPointer();
5028   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
5029   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
5030   for(int i=1;i<nbOfLevsInVec;i++)
5031     {
5032       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
5033       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
5034       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
5035       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
5036       tmp->translate(vec);
5037       double tmp3[2],radius,alpha,alpha0;
5038       const double *p0=i+1<nbOfLevsInVec?begin:third;
5039       const double *p1=i+1<nbOfLevsInVec?end:begin;
5040       const double *p2=i+1<nbOfLevsInVec?third:end;
5041       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
5042       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]);
5043       double angle=acos(cosangle/(radius*radius));
5044       tmp->rotate(end,0,angle);
5045       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
5046     }
5047   return ret.retn();
5048 }
5049
5050 /*!
5051  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
5052  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
5053  * \return newCoords new coords filled by this method. 
5054  */
5055 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
5056 {
5057   if(isQuad)
5058     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
5059   int oldNbOfNodes=getNumberOfNodes();
5060   int nbOf1DCells=mesh1D->getNumberOfCells();
5061   if(nbOf1DCells<2)
5062     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
5063   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
5064   int nbOfLevsInVec=nbOf1DCells+1;
5065   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
5066   double *retPtr=ret->getPointer();
5067   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
5068   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5069   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
5070   tmp->setCoords(tmp2);
5071   const double *coo1D=mesh1D->getCoords()->getConstPointer();
5072   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
5073   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
5074   for(int i=1;i<nbOfLevsInVec;i++)
5075     {
5076       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
5077       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
5078       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
5079       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
5080       tmp->translate(vec);
5081       double tmp3[2],radius,alpha,alpha0;
5082       const double *p0=i+1<nbOfLevsInVec?begin:third;
5083       const double *p1=i+1<nbOfLevsInVec?end:begin;
5084       const double *p2=i+1<nbOfLevsInVec?third:end;
5085       double vecPlane[3]={
5086         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
5087         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
5088         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
5089       };
5090       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
5091       if(norm>1.e-7)
5092         {
5093           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
5094           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
5095           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
5096           double s2=norm2;
5097           double c2=cos(asin(s2));
5098           double m[3][3]={
5099             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
5100             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
5101             {-vec2[1]*s2, vec2[0]*s2, c2}
5102           };
5103           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]};
5104           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]};
5105           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]};
5106           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
5107           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]);
5108           double angle=acos(cosangle/(radius*radius));
5109           tmp->rotate(end,vecPlane,angle);
5110         }
5111       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
5112     }
5113   return ret.retn();
5114 }
5115
5116 /*!
5117  * This method is private because not easy to use for end user. This method is const contrary to
5118  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
5119  * the coords sorted slice by slice.
5120  * \param isQuad specifies presence of quadratic cells.
5121  */
5122 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
5123 {
5124   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
5125   int nbOf2DCells(getNumberOfCells());
5126   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
5127   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
5128   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5129   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
5130   newConnI->alloc(nbOf3DCells+1,1);
5131   int *newConnIPtr(newConnI->getPointer());
5132   *newConnIPtr++=0;
5133   std::vector<int> newc;
5134   for(int j=0;j<nbOf2DCells;j++)
5135     {
5136       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
5137       *newConnIPtr++=(int)newc.size();
5138     }
5139   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
5140   int *newConnPtr(newConn->getPointer());
5141   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
5142   newConnIPtr=newConnI->getPointer();
5143   for(int iz=0;iz<nbOf1DCells;iz++)
5144     {
5145       if(iz!=0)
5146         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
5147       const int *posOfTypeOfCell(newConnIPtr);
5148       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
5149         {
5150           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
5151           if(icell!=*posOfTypeOfCell)
5152             {
5153               if(*iter!=-1)
5154                 *newConnPtr=(*iter)+iz*deltaPerLev;
5155               else
5156                 *newConnPtr=-1;
5157             }
5158           else
5159             {
5160               *newConnPtr=*iter;
5161               posOfTypeOfCell++;
5162             }
5163         }
5164     }
5165   ret->setConnectivity(newConn,newConnI,true);
5166   ret->setCoords(getCoords());
5167   return ret;
5168 }
5169
5170 /*!
5171  * Checks if \a this mesh is constituted by only quadratic cells.
5172  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
5173  *  \throw If the coordinates array is not set.
5174  *  \throw If the nodal connectivity of cells is not defined.
5175  */
5176 bool MEDCouplingUMesh::isFullyQuadratic() const
5177 {
5178   checkFullyDefined();
5179   bool ret=true;
5180   int nbOfCells=getNumberOfCells();
5181   for(int i=0;i<nbOfCells && ret;i++)
5182     {
5183       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5184       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5185       ret=cm.isQuadratic();
5186     }
5187   return ret;
5188 }
5189
5190 /*!
5191  * Checks if \a this mesh includes any quadratic cell.
5192  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5193  *  \throw If the coordinates array is not set.
5194  *  \throw If the nodal connectivity of cells is not defined.
5195  */
5196 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5197 {
5198   checkFullyDefined();
5199   bool ret=false;
5200   int nbOfCells=getNumberOfCells();
5201   for(int i=0;i<nbOfCells && !ret;i++)
5202     {
5203       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5204       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5205       ret=cm.isQuadratic();
5206     }
5207   return ret;
5208 }
5209
5210 /*!
5211  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5212  * this mesh, it remains unchanged.
5213  *  \throw If the coordinates array is not set.
5214  *  \throw If the nodal connectivity of cells is not defined.
5215  */
5216 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5217 {
5218   checkFullyDefined();
5219   int nbOfCells=getNumberOfCells();
5220   int delta=0;
5221   const int *iciptr=_nodal_connec_index->getConstPointer();
5222   for(int i=0;i<nbOfCells;i++)
5223     {
5224       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5225       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5226       if(cm.isQuadratic())
5227         {
5228           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5229           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5230           if(!cml.isDynamic())
5231             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5232           else
5233             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5234         }
5235     }
5236   if(delta==0)
5237     return ;
5238   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5239   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5240   const int *icptr=_nodal_connec->getConstPointer();
5241   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
5242   newConnI->alloc(nbOfCells+1,1);
5243   int *ocptr=newConn->getPointer();
5244   int *ociptr=newConnI->getPointer();
5245   *ociptr=0;
5246   _types.clear();
5247   for(int i=0;i<nbOfCells;i++,ociptr++)
5248     {
5249       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5250       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5251       if(!cm.isQuadratic())
5252         {
5253           _types.insert(type);
5254           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5255           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5256         }
5257       else
5258         {
5259           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5260           _types.insert(typel);
5261           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5262           int newNbOfNodes=cml.getNumberOfNodes();
5263           if(cml.isDynamic())
5264             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5265           *ocptr++=(int)typel;
5266           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5267           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5268         }
5269     }
5270   setConnectivity(newConn,newConnI,false);
5271 }
5272
5273 /*!
5274  * This method converts all linear cell in \a this to quadratic one.
5275  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5276  * 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)
5277  * 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.
5278  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5279  * end of the existing coordinates.
5280  * 
5281  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5282  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5283  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5284  * 
5285  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5286  *
5287  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5288  */
5289 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5290 {
5291   DataArrayInt *conn=0,*connI=0;
5292   DataArrayDouble *coords=0;
5293   std::set<INTERP_KERNEL::NormalizedCellType> types;
5294   checkFullyDefined();
5295   MCAuto<DataArrayInt> ret,connSafe,connISafe;
5296   MCAuto<DataArrayDouble> coordsSafe;
5297   int meshDim=getMeshDimension();
5298   switch(conversionType)
5299   {
5300     case 0:
5301       switch(meshDim)
5302       {
5303         case 1:
5304           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5305           connSafe=conn; connISafe=connI; coordsSafe=coords;
5306           break;
5307         case 2:
5308           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5309           connSafe=conn; connISafe=connI; coordsSafe=coords;
5310           break;
5311         case 3:
5312           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5313           connSafe=conn; connISafe=connI; coordsSafe=coords;
5314           break;
5315         default:
5316           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5317       }
5318       break;
5319         case 1:
5320           {
5321             switch(meshDim)
5322             {
5323               case 1:
5324                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5325                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5326                 break;
5327               case 2:
5328                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5329                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5330                 break;
5331               case 3:
5332                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5333                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5334                 break;
5335               default:
5336                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5337             }
5338             break;
5339           }
5340         default:
5341           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5342   }
5343   setConnectivity(connSafe,connISafe,false);
5344   _types=types;
5345   setCoords(coordsSafe);
5346   return ret.retn();
5347 }
5348
5349 /*!
5350  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5351  * so that the number of cells remains the same. Quadratic faces are converted to
5352  * polygons. This method works only for 2D meshes in
5353  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5354  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5355  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5356  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5357  *         a polylinized edge constituting the input polygon.
5358  *  \throw If the coordinates array is not set.
5359  *  \throw If the nodal connectivity of cells is not defined.
5360  *  \throw If \a this->getMeshDimension() != 2.
5361  *  \throw If \a this->getSpaceDimension() != 2.
5362  */
5363 void MEDCouplingUMesh::tessellate2D(double eps)
5364 {
5365   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
5366   if(spaceDim!=2)
5367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
5368   switch(meshDim)
5369     {
5370     case 1:
5371       return tessellate2DCurveInternal(eps);
5372     case 2:
5373       return tessellate2DInternal(eps);
5374     default:
5375       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
5376     }
5377 }
5378 /*!
5379  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5380  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5381  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5382  *         a sub-divided edge.
5383  *  \throw If the coordinates array is not set.
5384  *  \throw If the nodal connectivity of cells is not defined.
5385  *  \throw If \a this->getMeshDimension() != 1.
5386  *  \throw If \a this->getSpaceDimension() != 2.
5387  */
5388
5389 #if 0
5390 /*!
5391  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5392  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5393  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5394  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5395  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5396  * This method can be seen as the opposite method of colinearize2D.
5397  * 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
5398  * to avoid to modify the numbering of existing nodes.
5399  *
5400  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5401  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5402  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5403  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5404  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5405  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5406  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5407  *
5408  * \sa buildDescendingConnectivity2
5409  */
5410 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5411                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5412 {
5413   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5415   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5416   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5417     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5418   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5419     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5420   //DataArrayInt *out0(0),*outi0(0);
5421   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5422   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
5423   //out0s=out0s->buildUnique(); out0s->sort(true);
5424 }
5425 #endif
5426
5427 /*!
5428  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5429  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5430  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5431  */
5432 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5433 {
5434   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5435   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5436   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5437   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5438   int nbOfCells=getNumberOfCells();
5439   int nbOfNodes=getNumberOfNodes();
5440   const int *cPtr=_nodal_connec->getConstPointer();
5441   const int *icPtr=_nodal_connec_index->getConstPointer();
5442   int lastVal=0,offset=nbOfNodes;
5443   for(int i=0;i<nbOfCells;i++,icPtr++)
5444     {
5445       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5446       if(type==INTERP_KERNEL::NORM_SEG2)
5447         {
5448           types.insert(INTERP_KERNEL::NORM_SEG3);
5449           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5450           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5451           newConn->pushBackSilent(offset++);
5452           lastVal+=4;
5453           newConnI->pushBackSilent(lastVal);
5454           ret->pushBackSilent(i);
5455         }
5456       else
5457         {
5458           types.insert(type);
5459           lastVal+=(icPtr[1]-icPtr[0]);
5460           newConnI->pushBackSilent(lastVal);
5461           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5462         }
5463     }
5464   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5465   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5466   return ret.retn();
5467 }
5468
5469 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
5470 {
5471   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5472   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5473   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5474   //
5475   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5476   DataArrayInt *conn1D=0,*conn1DI=0;
5477   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5478   DataArrayDouble *coordsTmp=0;
5479   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5480   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5481   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5482   const int *c1DPtr=conn1D->begin();
5483   const int *c1DIPtr=conn1DI->begin();
5484   int nbOfCells=getNumberOfCells();
5485   const int *cPtr=_nodal_connec->getConstPointer();
5486   const int *icPtr=_nodal_connec_index->getConstPointer();
5487   int lastVal=0;
5488   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5489     {
5490       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5491       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5492       if(!cm.isQuadratic())
5493         {
5494           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5495           types.insert(typ2); newConn->pushBackSilent(typ2);
5496           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5497           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5498             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5499           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5500           newConnI->pushBackSilent(lastVal);
5501           ret->pushBackSilent(i);
5502         }
5503       else
5504         {
5505           types.insert(typ);
5506           lastVal+=(icPtr[1]-icPtr[0]);
5507           newConnI->pushBackSilent(lastVal);
5508           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5509         }
5510     }
5511   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5512   return ret.retn();
5513 }
5514
5515 /*!
5516  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5517  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5518  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5519  */
5520 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5521 {
5522   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5523   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5524   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5525 }
5526
5527 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5528 {
5529   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5530   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5531   //
5532   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5533   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5534   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5535   //
5536   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5537   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5538   DataArrayInt *conn1D=0,*conn1DI=0;
5539   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5540   DataArrayDouble *coordsTmp=0;
5541   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5542   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5543   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5544   const int *c1DPtr=conn1D->begin();
5545   const int *c1DIPtr=conn1DI->begin();
5546   int nbOfCells=getNumberOfCells();
5547   const int *cPtr=_nodal_connec->getConstPointer();
5548   const int *icPtr=_nodal_connec_index->getConstPointer();
5549   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5550   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5551     {
5552       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5553       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5554       if(!cm.isQuadratic())
5555         {
5556           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5557           types.insert(typ2); newConn->pushBackSilent(typ2);
5558           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5559           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5560             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5561           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5562           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5563           newConnI->pushBackSilent(lastVal);
5564           ret->pushBackSilent(i);
5565         }
5566       else
5567         {
5568           types.insert(typ);
5569           lastVal+=(icPtr[1]-icPtr[0]);
5570           newConnI->pushBackSilent(lastVal);
5571           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5572         }
5573     }
5574   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5575   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5576   return ret.retn();
5577 }
5578
5579 /*!
5580  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5581  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5582  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5583  */
5584 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5585 {
5586   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5587   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5588   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5589 }
5590
5591 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5592 {
5593   MCAuto<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5594   MCAuto<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5595   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5596   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5597   //
5598   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5599   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5600   MCAuto<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5601   //
5602   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5603   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5604   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5605   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5606   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5607   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5608   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5609   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5610   MCAuto<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5611   MCAuto<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5612   MCAuto<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5613   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5614   int nbOfCells=getNumberOfCells();
5615   const int *cPtr=_nodal_connec->getConstPointer();
5616   const int *icPtr=_nodal_connec_index->getConstPointer();
5617   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5618   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5619     {
5620       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5621       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5622       if(!cm.isQuadratic())
5623         {
5624           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5625           if(typ2==INTERP_KERNEL::NORM_ERROR)
5626             {
5627               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5628               throw INTERP_KERNEL::Exception(oss.str());
5629             }
5630           types.insert(typ2); newConn->pushBackSilent(typ2);
5631           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5632           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5633             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5634           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5635             {
5636               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5637               int tmpPos=newConn->getNumberOfTuples();
5638               newConn->pushBackSilent(nodeId2);
5639               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5640             }
5641           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5642           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5643           newConnI->pushBackSilent(lastVal);
5644           ret->pushBackSilent(i);
5645         }
5646       else
5647         {
5648           types.insert(typ);
5649           lastVal+=(icPtr[1]-icPtr[0]);
5650           newConnI->pushBackSilent(lastVal);
5651           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5652         }
5653     }
5654   MCAuto<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5655   MCAuto<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5656   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5657   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5658   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5659   int *c=newConn->getPointer();
5660   const int *cI(newConnI->begin());
5661   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5662     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5663   offset=coordsTmp2Safe->getNumberOfTuples();
5664   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5665     c[cI[(*elt)+1]-1]+=offset;
5666   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5667   return ret.retn();
5668 }
5669
5670 /*!
5671  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5672  * In addition, returns an array mapping new cells to old ones. <br>
5673  * This method typically increases the number of cells in \a this mesh
5674  * but the number of nodes remains \b unchanged.
5675  * That's why the 3D splitting policies
5676  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5677  *  \param [in] policy - specifies a pattern used for splitting.
5678  * The semantic of \a policy is:
5679  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5680  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5681  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5682  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5683  *
5684  *
5685  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5686  *          an id of old cell producing it. The caller is to delete this array using
5687  *         decrRef() as it is no more needed.
5688  *
5689  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5690  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5691  *          and \a this->getMeshDimension() != 3. 
5692  *  \throw If \a policy is not one of the four discussed above.
5693  *  \throw If the nodal connectivity of cells is not defined.
5694  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5695  */
5696 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5697 {
5698   switch(policy)
5699   {
5700     case 0:
5701       return simplexizePol0();
5702     case 1:
5703       return simplexizePol1();
5704     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5705         return simplexizePlanarFace5();
5706     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5707         return simplexizePlanarFace6();
5708     default:
5709       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)");
5710   }
5711 }
5712
5713 /*!
5714  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5715  * - 1D: INTERP_KERNEL::NORM_SEG2
5716  * - 2D: INTERP_KERNEL::NORM_TRI3
5717  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5718  *
5719  * This method is useful for users that need to use P1 field services as
5720  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5721  * All these methods need mesh support containing only simplex cells.
5722  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5723  *  \throw If the coordinates array is not set.
5724  *  \throw If the nodal connectivity of cells is not defined.
5725  *  \throw If \a this->getMeshDimension() < 1.
5726  */
5727 bool MEDCouplingUMesh::areOnlySimplexCells() const
5728 {
5729   checkFullyDefined();
5730   int mdim=getMeshDimension();
5731   if(mdim<1 || mdim>3)
5732     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5733   int nbCells=getNumberOfCells();
5734   const int *conn=_nodal_connec->getConstPointer();
5735   const int *connI=_nodal_connec_index->getConstPointer();
5736   for(int i=0;i<nbCells;i++)
5737     {
5738       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5739       if(!cm.isSimplex())
5740         return false;
5741     }
5742   return true;
5743 }
5744
5745 /*!
5746  * This method implements policy 0 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5747  */
5748 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5749 {
5750   checkConnectivityFullyDefined();
5751   if(getMeshDimension()!=2)
5752     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5753   int nbOfCells=getNumberOfCells();
5754   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5755   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5756   ret->alloc(nbOfCells+nbOfCutCells,1);
5757   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5758   int *retPt=ret->getPointer();
5759   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5760   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5761   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5762   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5763   int *pt=newConn->getPointer();
5764   int *ptI=newConnI->getPointer();
5765   ptI[0]=0;
5766   const int *oldc=_nodal_connec->getConstPointer();
5767   const int *ci=_nodal_connec_index->getConstPointer();
5768   for(int i=0;i<nbOfCells;i++,ci++)
5769     {
5770       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5771         {
5772           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5773             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5774           pt=std::copy(tmp,tmp+8,pt);
5775           ptI[1]=ptI[0]+4;
5776           ptI[2]=ptI[0]+8;
5777           *retPt++=i;
5778           *retPt++=i;
5779           ptI+=2;
5780         }
5781       else
5782         {
5783           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5784           ptI[1]=ptI[0]+ci[1]-ci[0];
5785           ptI++;
5786           *retPt++=i;
5787         }
5788     }
5789   _nodal_connec->decrRef();
5790   _nodal_connec=newConn.retn();
5791   _nodal_connec_index->decrRef();
5792   _nodal_connec_index=newConnI.retn();
5793   computeTypes();
5794   updateTime();
5795   return ret.retn();
5796 }
5797
5798 /*!
5799  * This method implements policy 1 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5800  */
5801 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5802 {
5803   checkConnectivityFullyDefined();
5804   if(getMeshDimension()!=2)
5805     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5806   int nbOfCells=getNumberOfCells();
5807   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5808   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5809   ret->alloc(nbOfCells+nbOfCutCells,1);
5810   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5811   int *retPt=ret->getPointer();
5812   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5813   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5814   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5815   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5816   int *pt=newConn->getPointer();
5817   int *ptI=newConnI->getPointer();
5818   ptI[0]=0;
5819   const int *oldc=_nodal_connec->getConstPointer();
5820   const int *ci=_nodal_connec_index->getConstPointer();
5821   for(int i=0;i<nbOfCells;i++,ci++)
5822     {
5823       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5824         {
5825           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5826             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5827           pt=std::copy(tmp,tmp+8,pt);
5828           ptI[1]=ptI[0]+4;
5829           ptI[2]=ptI[0]+8;
5830           *retPt++=i;
5831           *retPt++=i;
5832           ptI+=2;
5833         }
5834       else
5835         {
5836           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5837           ptI[1]=ptI[0]+ci[1]-ci[0];
5838           ptI++;
5839           *retPt++=i;
5840         }
5841     }
5842   _nodal_connec->decrRef();
5843   _nodal_connec=newConn.retn();
5844   _nodal_connec_index->decrRef();
5845   _nodal_connec_index=newConnI.retn();
5846   computeTypes();
5847   updateTime();
5848   return ret.retn();
5849 }
5850
5851 /*!
5852  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5853  */
5854 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5855 {
5856   checkConnectivityFullyDefined();
5857   if(getMeshDimension()!=3)
5858     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5859   int nbOfCells=getNumberOfCells();
5860   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5861   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5862   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5863   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5864   int *retPt=ret->getPointer();
5865   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5866   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5867   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5868   newConn->alloc(getNodalConnectivityArrayLen()+16*nbOfCutCells,1);//21
5869   int *pt=newConn->getPointer();
5870   int *ptI=newConnI->getPointer();
5871   ptI[0]=0;
5872   const int *oldc=_nodal_connec->getConstPointer();
5873   const int *ci=_nodal_connec_index->getConstPointer();
5874   for(int i=0;i<nbOfCells;i++,ci++)
5875     {
5876       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5877         {
5878           for(int j=0;j<5;j++,pt+=5,ptI++)
5879             {
5880               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5881               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];
5882               *retPt++=i;
5883               ptI[1]=ptI[0]+5;
5884             }
5885         }
5886       else
5887         {
5888           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5889           ptI[1]=ptI[0]+ci[1]-ci[0];
5890           ptI++;
5891           *retPt++=i;
5892         }
5893     }
5894   _nodal_connec->decrRef();
5895   _nodal_connec=newConn.retn();
5896   _nodal_connec_index->decrRef();
5897   _nodal_connec_index=newConnI.retn();
5898   computeTypes();
5899   updateTime();
5900   return ret.retn();
5901 }
5902
5903 /*!
5904  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5905  */
5906 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5907 {
5908   checkConnectivityFullyDefined();
5909   if(getMeshDimension()!=3)
5910     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5911   int nbOfCells=getNumberOfCells();
5912   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5913   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5914   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5915   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5916   int *retPt=ret->getPointer();
5917   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5918   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5919   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5920   newConn->alloc(getNodalConnectivityArrayLen()+21*nbOfCutCells,1);
5921   int *pt=newConn->getPointer();
5922   int *ptI=newConnI->getPointer();
5923   ptI[0]=0;
5924   const int *oldc=_nodal_connec->getConstPointer();
5925   const int *ci=_nodal_connec_index->getConstPointer();
5926   for(int i=0;i<nbOfCells;i++,ci++)
5927     {
5928       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5929         {
5930           for(int j=0;j<6;j++,pt+=5,ptI++)
5931             {
5932               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5933               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];
5934               *retPt++=i;
5935               ptI[1]=ptI[0]+5;
5936             }
5937         }
5938       else
5939         {
5940           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5941           ptI[1]=ptI[0]+ci[1]-ci[0];
5942           ptI++;
5943           *retPt++=i;
5944         }
5945     }
5946   _nodal_connec->decrRef();
5947   _nodal_connec=newConn.retn();
5948   _nodal_connec_index->decrRef();
5949   _nodal_connec_index=newConnI.retn();
5950   computeTypes();
5951   updateTime();
5952   return ret.retn();
5953 }
5954
5955 /*!
5956  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5957  * so that the number of cells remains the same. Quadratic faces are converted to
5958  * polygons. This method works only for 2D meshes in
5959  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5960  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5961  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5962  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5963  *         a polylinized edge constituting the input polygon.
5964  *  \throw If the coordinates array is not set.
5965  *  \throw If the nodal connectivity of cells is not defined.
5966  *  \throw If \a this->getMeshDimension() != 2.
5967  *  \throw If \a this->getSpaceDimension() != 2.
5968  */
5969 void MEDCouplingUMesh::tessellate2DInternal(double eps)
5970 {
5971   checkFullyDefined();
5972   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5973     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5974   double epsa=fabs(eps);
5975   if(epsa<std::numeric_limits<double>::min())
5976     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 !");
5977   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
5978   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
5979   revDesc1=0; revDescIndx1=0;
5980   mDesc->tessellate2D(eps);
5981   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5982   setCoords(mDesc->getCoords());
5983 }
5984
5985 /*!
5986  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5987  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5988  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5989  *         a sub-divided edge.
5990  *  \throw If the coordinates array is not set.
5991  *  \throw If the nodal connectivity of cells is not defined.
5992  *  \throw If \a this->getMeshDimension() != 1.
5993  *  \throw If \a this->getSpaceDimension() != 2.
5994  */
5995 void MEDCouplingUMesh::tessellate2DCurveInternal(double eps)
5996 {
5997   checkFullyDefined();
5998   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5999     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
6000   double epsa=fabs(eps);
6001   if(epsa<std::numeric_limits<double>::min())
6002     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 !");
6003   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
6004   int nbCells=getNumberOfCells();
6005   int nbNodes=getNumberOfNodes();
6006   const int *conn=_nodal_connec->getConstPointer();
6007   const int *connI=_nodal_connec_index->getConstPointer();
6008   const double *coords=_coords->getConstPointer();
6009   std::vector<double> addCoo;
6010   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
6011   MCAuto<DataArrayInt> newConnI(DataArrayInt::New());
6012   newConnI->alloc(nbCells+1,1);
6013   int *newConnIPtr=newConnI->getPointer();
6014   *newConnIPtr=0;
6015   int tmp1[3];
6016   INTERP_KERNEL::Node *tmp2[3];
6017   std::set<INTERP_KERNEL::NormalizedCellType> types;
6018   for(int i=0;i<nbCells;i++,newConnIPtr++)
6019     {
6020       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6021       if(cm.isQuadratic())
6022         {//assert(connI[i+1]-connI[i]-1==3)
6023           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
6024           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
6025           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
6026           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
6027           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
6028           if(eac)
6029             {
6030               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
6031               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
6032               delete eac;
6033               newConnIPtr[1]=(int)newConn.size();
6034             }
6035           else
6036             {
6037               types.insert(INTERP_KERNEL::NORM_SEG2);
6038               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
6039               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
6040               newConnIPtr[1]=newConnIPtr[0]+3;
6041             }
6042         }
6043       else
6044         {
6045           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6046           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
6047           newConnIPtr[1]=newConnIPtr[0]+3;
6048         }
6049     }
6050   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
6051     return ;
6052   _types=types;
6053   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
6054   MCAuto<DataArrayInt> newConnArr=DataArrayInt::New();
6055   newConnArr->alloc((int)newConn.size(),1);
6056   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
6057   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
6058   MCAuto<DataArrayDouble> newCoords=DataArrayDouble::New();
6059   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
6060   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
6061   std::copy(addCoo.begin(),addCoo.end(),work);
6062   DataArrayDouble::SetArrayIn(newCoords,_coords);
6063   updateTime();
6064 }
6065
6066 /*!
6067  * 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.
6068  * This method completly ignore coordinates.
6069  * \param nodeSubdived is the nodal connectivity of subdivision of edges
6070  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
6071  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
6072  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
6073  */
6074 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
6075 {
6076   checkFullyDefined();
6077   if(getMeshDimension()!=2)
6078     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
6079   int nbOfCells=getNumberOfCells();
6080   int *connI=_nodal_connec_index->getPointer();
6081   int newConnLgth=0;
6082   for(int i=0;i<nbOfCells;i++,connI++)
6083     {
6084       int offset=descIndex[i];
6085       int nbOfEdges=descIndex[i+1]-offset;
6086       //
6087       bool ddirect=desc[offset+nbOfEdges-1]>0;
6088       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
6089       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
6090       for(int j=0;j<nbOfEdges;j++)
6091         {
6092           bool direct=desc[offset+j]>0;
6093           int edgeId=std::abs(desc[offset+j])-1;
6094           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
6095             {
6096               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
6097               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
6098               int ref2=direct?id1:id2;
6099               if(ref==ref2)
6100                 {
6101                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
6102                   newConnLgth+=nbOfSubNodes-1;
6103                   ref=direct?id2:id1;
6104                 }
6105               else
6106                 {
6107                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
6108                   throw INTERP_KERNEL::Exception(oss.str());
6109                 }
6110             }
6111           else
6112             {
6113               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
6114             }
6115         }
6116       newConnLgth++;//+1 is for cell type
6117       connI[1]=newConnLgth;
6118     }
6119   //
6120   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
6121   newConn->alloc(newConnLgth,1);
6122   int *work=newConn->getPointer();
6123   for(int i=0;i<nbOfCells;i++)
6124     {
6125       *work++=INTERP_KERNEL::NORM_POLYGON;
6126       int offset=descIndex[i];
6127       int nbOfEdges=descIndex[i+1]-offset;
6128       for(int j=0;j<nbOfEdges;j++)
6129         {
6130           bool direct=desc[offset+j]>0;
6131           int edgeId=std::abs(desc[offset+j])-1;
6132           if(direct)
6133             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
6134           else
6135             {
6136               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
6137               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
6138               work=std::copy(it,it+nbOfSubNodes-1,work);
6139             }
6140         }
6141     }
6142   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
6143   _types.clear();
6144   if(nbOfCells>0)
6145     _types.insert(INTERP_KERNEL::NORM_POLYGON);
6146 }
6147
6148 /*!
6149  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
6150  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
6151  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
6152  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
6153  * so it can be useful to call mergeNodes() before calling this method.
6154  *  \throw If \a this->getMeshDimension() <= 1.
6155  *  \throw If the coordinates array is not set.
6156  *  \throw If the nodal connectivity of cells is not defined.
6157  */
6158 void MEDCouplingUMesh::convertDegeneratedCells()
6159 {
6160   checkFullyDefined();
6161   if(getMeshDimension()<=1)
6162     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
6163   int nbOfCells=getNumberOfCells();
6164   if(nbOfCells<1)
6165     return ;
6166   int initMeshLgth=getNodalConnectivityArrayLen();
6167   int *conn=_nodal_connec->getPointer();
6168   int *index=_nodal_connec_index->getPointer();
6169   int posOfCurCell=0;
6170   int newPos=0;
6171   int lgthOfCurCell;
6172   for(int i=0;i<nbOfCells;i++)
6173     {
6174       lgthOfCurCell=index[i+1]-posOfCurCell;
6175       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
6176       int newLgth;
6177       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
6178                                                                                                      conn+newPos+1,newLgth);
6179       conn[newPos]=newType;
6180       newPos+=newLgth+1;
6181       posOfCurCell=index[i+1];
6182       index[i+1]=newPos;
6183     }
6184   if(newPos!=initMeshLgth)
6185     _nodal_connec->reAlloc(newPos);
6186   computeTypes();
6187 }
6188
6189 /*!
6190  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6191  * A cell is considered to be oriented correctly if an angle between its
6192  * normal vector and a given vector is less than \c PI / \c 2.
6193  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6194  *         cells. 
6195  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6196  *         checked.
6197  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6198  *         is not cleared before filling in.
6199  *  \throw If \a this->getMeshDimension() != 2.
6200  *  \throw If \a this->getSpaceDimension() != 3.
6201  *
6202  *  \if ENABLE_EXAMPLES
6203  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6204  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6205  *  \endif
6206  */
6207 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6208 {
6209   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6210     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6211   int nbOfCells=getNumberOfCells();
6212   const int *conn=_nodal_connec->getConstPointer();
6213   const int *connI=_nodal_connec_index->getConstPointer();
6214   const double *coordsPtr=_coords->getConstPointer();
6215   for(int i=0;i<nbOfCells;i++)
6216     {
6217       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6218       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6219         {
6220           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6221           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6222             cells.push_back(i);
6223         }
6224     }
6225 }
6226
6227 /*!
6228  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6229  * considered to be oriented correctly if an angle between its normal vector and a
6230  * given vector is less than \c PI / \c 2. 
6231  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6232  *         cells. 
6233  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6234  *         checked.
6235  *  \throw If \a this->getMeshDimension() != 2.
6236  *  \throw If \a this->getSpaceDimension() != 3.
6237  *
6238  *  \if ENABLE_EXAMPLES
6239  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6240  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6241  *  \endif
6242  *
6243  *  \sa changeOrientationOfCells
6244  */
6245 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6246 {
6247   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6248     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6249   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6250   const int *connI(_nodal_connec_index->getConstPointer());
6251   const double *coordsPtr(_coords->getConstPointer());
6252   bool isModified(false);
6253   for(int i=0;i<nbOfCells;i++)
6254     {
6255       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6256       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6257         {
6258           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6259           bool isQuadratic(cm.isQuadratic());
6260           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6261             {
6262               isModified=true;
6263               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6264             }
6265         }
6266     }
6267   if(isModified)
6268     _nodal_connec->declareAsNew();
6269   updateTime();
6270 }
6271
6272 /*!
6273  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6274  *
6275  * \sa orientCorrectly2DCells
6276  */
6277 void MEDCouplingUMesh::changeOrientationOfCells()
6278 {
6279   int mdim(getMeshDimension());
6280   if(mdim!=2 && mdim!=1)
6281     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6282   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6283   const int *connI(_nodal_connec_index->getConstPointer());
6284   if(mdim==2)
6285     {//2D
6286       for(int i=0;i<nbOfCells;i++)
6287         {
6288           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6289           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6290           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6291         }
6292     }
6293   else
6294     {//1D
6295       for(int i=0;i<nbOfCells;i++)
6296         {
6297           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6298           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6299           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6300         }
6301     }
6302 }
6303
6304 /*!
6305  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6306  * oriented facets. The normal vector of the facet should point out of the cell.
6307  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6308  *         is not cleared before filling in.
6309  *  \throw If \a this->getMeshDimension() != 3.
6310  *  \throw If \a this->getSpaceDimension() != 3.
6311  *  \throw If the coordinates array is not set.
6312  *  \throw If the nodal connectivity of cells is not defined.
6313  *
6314  *  \if ENABLE_EXAMPLES
6315  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6316  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6317  *  \endif
6318  */
6319 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6320 {
6321   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6322     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6323   int nbOfCells=getNumberOfCells();
6324   const int *conn=_nodal_connec->getConstPointer();
6325   const int *connI=_nodal_connec_index->getConstPointer();
6326   const double *coordsPtr=_coords->getConstPointer();
6327   for(int i=0;i<nbOfCells;i++)
6328     {
6329       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6330       if(type==INTERP_KERNEL::NORM_POLYHED)
6331         {
6332           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6333             cells.push_back(i);
6334         }
6335     }
6336 }
6337
6338 /*!
6339  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6340  * out of the cell. 
6341  *  \throw If \a this->getMeshDimension() != 3.
6342  *  \throw If \a this->getSpaceDimension() != 3.
6343  *  \throw If the coordinates array is not set.
6344  *  \throw If the nodal connectivity of cells is not defined.
6345  *  \throw If the reparation fails.
6346  *
6347  *  \if ENABLE_EXAMPLES
6348  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6349  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6350  *  \endif
6351  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6352  */
6353 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6354 {
6355   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6356     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6357   int nbOfCells=getNumberOfCells();
6358   int *conn=_nodal_connec->getPointer();
6359   const int *connI=_nodal_connec_index->getConstPointer();
6360   const double *coordsPtr=_coords->getConstPointer();
6361   for(int i=0;i<nbOfCells;i++)
6362     {
6363       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6364       if(type==INTERP_KERNEL::NORM_POLYHED)
6365         {
6366           try
6367           {
6368               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6369                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6370           }
6371           catch(INTERP_KERNEL::Exception& e)
6372           {
6373               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6374               throw INTERP_KERNEL::Exception(oss.str());
6375           }
6376         }
6377     }
6378   updateTime();
6379 }
6380
6381 /*!
6382  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6383  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6384  * according to which the first facet of the cell should be oriented to have the normal vector
6385  * pointing out of cell.
6386  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6387  *         cells. The caller is to delete this array using decrRef() as it is no more
6388  *         needed. 
6389  *  \throw If \a this->getMeshDimension() != 3.
6390  *  \throw If \a this->getSpaceDimension() != 3.
6391  *  \throw If the coordinates array is not set.
6392  *  \throw If the nodal connectivity of cells is not defined.
6393  *
6394  *  \if ENABLE_EXAMPLES
6395  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6396  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6397  *  \endif
6398  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6399  */
6400 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6401 {
6402   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6403   if(getMeshDimension()!=3)
6404     throw INTERP_KERNEL::Exception(msg);
6405   int spaceDim=getSpaceDimension();
6406   if(spaceDim!=3)
6407     throw INTERP_KERNEL::Exception(msg);
6408   //
6409   int nbOfCells=getNumberOfCells();
6410   int *conn=_nodal_connec->getPointer();
6411   const int *connI=_nodal_connec_index->getConstPointer();
6412   const double *coo=getCoords()->getConstPointer();
6413   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6414   for(int i=0;i<nbOfCells;i++)
6415     {
6416       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6417       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6418         {
6419           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6420             {
6421               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6422               cells->pushBackSilent(i);
6423             }
6424         }
6425     }
6426   return cells.retn();
6427 }
6428
6429 /*!
6430  * This method is a faster method to correct orientation of all 3D cells in \a this.
6431  * 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.
6432  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
6433  * 
6434  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6435  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6436  */
6437 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6438 {
6439   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6440     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6441   int nbOfCells=getNumberOfCells();
6442   int *conn=_nodal_connec->getPointer();
6443   const int *connI=_nodal_connec_index->getConstPointer();
6444   const double *coordsPtr=_coords->getConstPointer();
6445   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6446   for(int i=0;i<nbOfCells;i++)
6447     {
6448       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6449       switch(type)
6450       {
6451         case INTERP_KERNEL::NORM_TETRA4:
6452           {
6453             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6454               {
6455                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6456                 ret->pushBackSilent(i);
6457               }
6458             break;
6459           }
6460         case INTERP_KERNEL::NORM_PYRA5:
6461           {
6462             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6463               {
6464                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6465                 ret->pushBackSilent(i);
6466               }
6467             break;
6468           }
6469         case INTERP_KERNEL::NORM_PENTA6:
6470         case INTERP_KERNEL::NORM_HEXA8:
6471         case INTERP_KERNEL::NORM_HEXGP12:
6472           {
6473             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6474               {
6475                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6476                 ret->pushBackSilent(i);
6477               }
6478             break;
6479           }
6480         case INTERP_KERNEL::NORM_POLYHED:
6481           {
6482             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6483               {
6484                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6485                 ret->pushBackSilent(i);
6486               }
6487             break;
6488           }
6489         default:
6490           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 !");
6491       }
6492     }
6493   updateTime();
6494   return ret.retn();
6495 }
6496
6497 /*!
6498  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6499  * If it is not the case an exception will be thrown.
6500  * This method is fast because the first cell of \a this is used to compute the plane.
6501  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6502  * \param pos output of size at least 3 used to store a point owned of searched plane.
6503  */
6504 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6505 {
6506   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6507     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6508   const int *conn=_nodal_connec->getConstPointer();
6509   const int *connI=_nodal_connec_index->getConstPointer();
6510   const double *coordsPtr=_coords->getConstPointer();
6511   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6512   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6513 }
6514
6515 /*!
6516  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6517  * cells. Currently cells of the following types are treated:
6518  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6519  * For a cell of other type an exception is thrown.
6520  * Space dimension of a 2D mesh can be either 2 or 3.
6521  * The Edge Ratio of a cell \f$t\f$ is: 
6522  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6523  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6524  *  the smallest edge lengths of \f$t\f$.
6525  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6526  *          cells and one time, lying on \a this mesh. The caller is to delete this
6527  *          field using decrRef() as it is no more needed. 
6528  *  \throw If the coordinates array is not set.
6529  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6530  *  \throw If the connectivity data array has more than one component.
6531  *  \throw If the connectivity data array has a named component.
6532  *  \throw If the connectivity index data array has more than one component.
6533  *  \throw If the connectivity index data array has a named component.
6534  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6535  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6536  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6537  */
6538 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6539 {
6540   checkConsistencyLight();
6541   int spaceDim=getSpaceDimension();
6542   int meshDim=getMeshDimension();
6543   if(spaceDim!=2 && spaceDim!=3)
6544     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6545   if(meshDim!=2 && meshDim!=3)
6546     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6547   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6548   ret->setMesh(this);
6549   int nbOfCells=getNumberOfCells();
6550   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6551   arr->alloc(nbOfCells,1);
6552   double *pt=arr->getPointer();
6553   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6554   const int *conn=_nodal_connec->getConstPointer();
6555   const int *connI=_nodal_connec_index->getConstPointer();
6556   const double *coo=_coords->getConstPointer();
6557   double tmp[12];
6558   for(int i=0;i<nbOfCells;i++,pt++)
6559     {
6560       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6561       switch(t)
6562       {
6563         case INTERP_KERNEL::NORM_TRI3:
6564           {
6565             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6566             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6567             break;
6568           }
6569         case INTERP_KERNEL::NORM_QUAD4:
6570           {
6571             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6572             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6573             break;
6574           }
6575         case INTERP_KERNEL::NORM_TETRA4:
6576           {
6577             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6578             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6579             break;
6580           }
6581         default:
6582           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6583       }
6584       conn+=connI[i+1]-connI[i];
6585     }
6586   ret->setName("EdgeRatio");
6587   ret->synchronizeTimeWithSupport();
6588   return ret.retn();
6589 }
6590
6591 /*!
6592  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6593  * cells. Currently cells of the following types are treated:
6594  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6595  * For a cell of other type an exception is thrown.
6596  * Space dimension of a 2D mesh can be either 2 or 3.
6597  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6598  *          cells and one time, lying on \a this mesh. The caller is to delete this
6599  *          field using decrRef() as it is no more needed. 
6600  *  \throw If the coordinates array is not set.
6601  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6602  *  \throw If the connectivity data array has more than one component.
6603  *  \throw If the connectivity data array has a named component.
6604  *  \throw If the connectivity index data array has more than one component.
6605  *  \throw If the connectivity index data array has a named component.
6606  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6607  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6608  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6609  */
6610 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6611 {
6612   checkConsistencyLight();
6613   int spaceDim=getSpaceDimension();
6614   int meshDim=getMeshDimension();
6615   if(spaceDim!=2 && spaceDim!=3)
6616     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6617   if(meshDim!=2 && meshDim!=3)
6618     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6619   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6620   ret->setMesh(this);
6621   int nbOfCells=getNumberOfCells();
6622   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6623   arr->alloc(nbOfCells,1);
6624   double *pt=arr->getPointer();
6625   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6626   const int *conn=_nodal_connec->getConstPointer();
6627   const int *connI=_nodal_connec_index->getConstPointer();
6628   const double *coo=_coords->getConstPointer();
6629   double tmp[12];
6630   for(int i=0;i<nbOfCells;i++,pt++)
6631     {
6632       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6633       switch(t)
6634       {
6635         case INTERP_KERNEL::NORM_TRI3:
6636           {
6637             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6638             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6639             break;
6640           }
6641         case INTERP_KERNEL::NORM_QUAD4:
6642           {
6643             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6644             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6645             break;
6646           }
6647         case INTERP_KERNEL::NORM_TETRA4:
6648           {
6649             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6650             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6651             break;
6652           }
6653         default:
6654           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6655       }
6656       conn+=connI[i+1]-connI[i];
6657     }
6658   ret->setName("AspectRatio");
6659   ret->synchronizeTimeWithSupport();
6660   return ret.retn();
6661 }
6662
6663 /*!
6664  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6665  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
6666  * in 3D space. Currently only cells of the following types are
6667  * treated: INTERP_KERNEL::NORM_QUAD4.
6668  * For a cell of other type an exception is thrown.
6669  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
6670  * Defining
6671  * \f$t=\vec{da}\times\vec{ab}\f$,
6672  * \f$u=\vec{ab}\times\vec{bc}\f$
6673  * \f$v=\vec{bc}\times\vec{cd}\f$
6674  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
6675  *  \f[
6676  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
6677  *  \f]
6678  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6679  *          cells and one time, lying on \a this mesh. The caller is to delete this
6680  *          field using decrRef() as it is no more needed. 
6681  *  \throw If the coordinates array is not set.
6682  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6683  *  \throw If the connectivity data array has more than one component.
6684  *  \throw If the connectivity data array has a named component.
6685  *  \throw If the connectivity index data array has more than one component.
6686  *  \throw If the connectivity index data array has a named component.
6687  *  \throw If \a this->getMeshDimension() != 2.
6688  *  \throw If \a this->getSpaceDimension() != 3.
6689  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6690  */
6691 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6692 {
6693   checkConsistencyLight();
6694   int spaceDim=getSpaceDimension();
6695   int meshDim=getMeshDimension();
6696   if(spaceDim!=3)
6697     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6698   if(meshDim!=2)
6699     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6700   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6701   ret->setMesh(this);
6702   int nbOfCells=getNumberOfCells();
6703   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6704   arr->alloc(nbOfCells,1);
6705   double *pt=arr->getPointer();
6706   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6707   const int *conn=_nodal_connec->getConstPointer();
6708   const int *connI=_nodal_connec_index->getConstPointer();
6709   const double *coo=_coords->getConstPointer();
6710   double tmp[12];
6711   for(int i=0;i<nbOfCells;i++,pt++)
6712     {
6713       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6714       switch(t)
6715       {
6716         case INTERP_KERNEL::NORM_QUAD4:
6717           {
6718             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6719             *pt=INTERP_KERNEL::quadWarp(tmp);
6720             break;
6721           }
6722         default:
6723           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6724       }
6725       conn+=connI[i+1]-connI[i];
6726     }
6727   ret->setName("Warp");
6728   ret->synchronizeTimeWithSupport();
6729   return ret.retn();
6730 }
6731
6732
6733 /*!
6734  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6735  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6736  * treated: INTERP_KERNEL::NORM_QUAD4.
6737  * The skew is computed as follow for a quad with points (a,b,c,d): let
6738  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
6739  * then the skew is computed as:
6740  *  \f[
6741  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
6742  *  \f]
6743  *
6744  * For a cell of other type an exception is thrown.
6745  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6746  *          cells and one time, lying on \a this mesh. The caller is to delete this
6747  *          field using decrRef() as it is no more needed. 
6748  *  \throw If the coordinates array is not set.
6749  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6750  *  \throw If the connectivity data array has more than one component.
6751  *  \throw If the connectivity data array has a named component.
6752  *  \throw If the connectivity index data array has more than one component.
6753  *  \throw If the connectivity index data array has a named component.
6754  *  \throw If \a this->getMeshDimension() != 2.
6755  *  \throw If \a this->getSpaceDimension() != 3.
6756  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6757  */
6758 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6759 {
6760   checkConsistencyLight();
6761   int spaceDim=getSpaceDimension();
6762   int meshDim=getMeshDimension();
6763   if(spaceDim!=3)
6764     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6765   if(meshDim!=2)
6766     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6767   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6768   ret->setMesh(this);
6769   int nbOfCells=getNumberOfCells();
6770   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6771   arr->alloc(nbOfCells,1);
6772   double *pt=arr->getPointer();
6773   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6774   const int *conn=_nodal_connec->getConstPointer();
6775   const int *connI=_nodal_connec_index->getConstPointer();
6776   const double *coo=_coords->getConstPointer();
6777   double tmp[12];
6778   for(int i=0;i<nbOfCells;i++,pt++)
6779     {
6780       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6781       switch(t)
6782       {
6783         case INTERP_KERNEL::NORM_QUAD4:
6784           {
6785             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6786             *pt=INTERP_KERNEL::quadSkew(tmp);
6787             break;
6788           }
6789         default:
6790           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6791       }
6792       conn+=connI[i+1]-connI[i];
6793     }
6794   ret->setName("Skew");
6795   ret->synchronizeTimeWithSupport();
6796   return ret.retn();
6797 }
6798
6799 /*!
6800  * 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.
6801  *
6802  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6803  *
6804  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6805  */
6806 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6807 {
6808   checkConsistencyLight();
6809   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6810   ret->setMesh(this);
6811   std::set<INTERP_KERNEL::NormalizedCellType> types;
6812   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6813   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6814   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6815   arr->alloc(nbCells,1);
6816   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6817     {
6818       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6819       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
6820       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6821     }
6822   ret->setArray(arr);
6823   ret->setName("Diameter");
6824   return ret.retn();
6825 }
6826
6827 /*!
6828  * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax).
6829  * 
6830  * \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)
6831  *                         For all other cases this input parameter is ignored.
6832  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6833  * 
6834  * \throw If \a this is not fully set (coordinates and connectivity).
6835  * \throw If a cell in \a this has no valid nodeId.
6836  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6837  */
6838 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6839 {
6840   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6841   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.
6842     return getBoundingBoxForBBTreeFast();
6843   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6844     {
6845       bool presenceOfQuadratic(false);
6846       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6847         {
6848           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6849           if(cm.isQuadratic())
6850             presenceOfQuadratic=true;
6851         }
6852       if(!presenceOfQuadratic)
6853         return getBoundingBoxForBBTreeFast();
6854       if(mDim==2 && sDim==2)
6855         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6856       else
6857         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6858     }
6859   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) !");
6860 }
6861
6862 /*!
6863  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6864  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6865  * 
6866  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6867  * 
6868  * \throw If \a this is not fully set (coordinates and connectivity).
6869  * \throw If a cell in \a this has no valid nodeId.
6870  */
6871 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6872 {
6873   checkFullyDefined();
6874   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6875   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6876   double *bbox(ret->getPointer());
6877   for(int i=0;i<nbOfCells*spaceDim;i++)
6878     {
6879       bbox[2*i]=std::numeric_limits<double>::max();
6880       bbox[2*i+1]=-std::numeric_limits<double>::max();
6881     }
6882   const double *coordsPtr(_coords->getConstPointer());
6883   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6884   for(int i=0;i<nbOfCells;i++)
6885     {
6886       int offset=connI[i]+1;
6887       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6888       for(int j=0;j<nbOfNodesForCell;j++)
6889         {
6890           int nodeId=conn[offset+j];
6891           if(nodeId>=0 && nodeId<nbOfNodes)
6892             {
6893               for(int k=0;k<spaceDim;k++)
6894                 {
6895                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6896                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6897                 }
6898               kk++;
6899             }
6900         }
6901       if(kk==0)
6902         {
6903           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6904           throw INTERP_KERNEL::Exception(oss.str());
6905         }
6906     }
6907   return ret.retn();
6908 }
6909
6910 /*!
6911  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6912  * useful for 2D meshes having quadratic cells
6913  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6914  * the two extremities of the arc of circle).
6915  * 
6916  * \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)
6917  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6918  * \throw If \a this is not fully defined.
6919  * \throw If \a this is not a mesh with meshDimension equal to 2.
6920  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6921  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6922  */
6923 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6924 {
6925   checkFullyDefined();
6926   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6927   if(spaceDim!=2 || mDim!=2)
6928     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!");
6929   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6930   double *bbox(ret->getPointer());
6931   const double *coords(_coords->getConstPointer());
6932   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6933   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6934     {
6935       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6936       int sz(connI[1]-connI[0]-1);
6937       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6938       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6939       INTERP_KERNEL::QuadraticPolygon *pol(0);
6940       for(int j=0;j<sz;j++)
6941         {
6942           int nodeId(conn[*connI+1+j]);
6943           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6944         }
6945       if(!cm.isQuadratic())
6946         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6947       else
6948         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6949       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6950       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6951     }
6952   return ret.retn();
6953 }
6954
6955 /*!
6956  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6957  * useful for 2D meshes having quadratic cells
6958  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6959  * the two extremities of the arc of circle).
6960  * 
6961  * \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)
6962  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6963  * \throw If \a this is not fully defined.
6964  * \throw If \a this is not a mesh with meshDimension equal to 1.
6965  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6966  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6967  */
6968 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6969 {
6970   checkFullyDefined();
6971   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6972   if(spaceDim!=2 || mDim!=1)
6973     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!");
6974   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6975   double *bbox(ret->getPointer());
6976   const double *coords(_coords->getConstPointer());
6977   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6978   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6979     {
6980       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6981       int sz(connI[1]-connI[0]-1);
6982       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6983       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6984       INTERP_KERNEL::Edge *edge(0);
6985       for(int j=0;j<sz;j++)
6986         {
6987           int nodeId(conn[*connI+1+j]);
6988           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6989         }
6990       if(!cm.isQuadratic())
6991         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6992       else
6993         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6994       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6995       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6996     }
6997   return ret.retn();
6998 }
6999
7000 /// @cond INTERNAL
7001
7002 namespace MEDCouplingImpl
7003 {
7004   class ConnReader
7005   {
7006   public:
7007     ConnReader(const int *c, int val):_conn(c),_val(val) { }
7008     bool operator() (const int& pos) { return _conn[pos]!=_val; }
7009   private:
7010     const int *_conn;
7011     int _val;
7012   };
7013
7014   class ConnReader2
7015   {
7016   public:
7017     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
7018     bool operator() (const int& pos) { return _conn[pos]==_val; }
7019   private:
7020     const int *_conn;
7021     int _val;
7022   };
7023 }
7024
7025 /// @endcond
7026
7027 /*!
7028  * This method expects that \a this is sorted by types. If not an exception will be thrown.
7029  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
7030  * \a this is composed in cell types.
7031  * The returned array is of size 3*n where n is the number of different types present in \a this. 
7032  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
7033  * This parameter is kept only for compatibility with other methode listed above.
7034  */
7035 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
7036 {
7037   checkConnectivityFullyDefined();
7038   const int *conn=_nodal_connec->getConstPointer();
7039   const int *connI=_nodal_connec_index->getConstPointer();
7040   const int *work=connI;
7041   int nbOfCells=getNumberOfCells();
7042   std::size_t n=getAllGeoTypes().size();
7043   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
7044   std::set<INTERP_KERNEL::NormalizedCellType> types;
7045   for(std::size_t i=0;work!=connI+nbOfCells;i++)
7046     {
7047       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
7048       if(types.find(typ)!=types.end())
7049         {
7050           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
7051           oss << " is not contiguous !";
7052           throw INTERP_KERNEL::Exception(oss.str());
7053         }
7054       types.insert(typ);
7055       ret[3*i]=typ;
7056       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
7057       ret[3*i+1]=(int)std::distance(work,work2);
7058       work=work2;
7059     }
7060   return ret;
7061 }
7062
7063 /*!
7064  * This method is used to check that this has contiguous cell type in same order than described in \a code.
7065  * only for types cell, type node is not managed.
7066  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
7067  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
7068  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
7069  * If 2 or more same geometric type is in \a code and exception is thrown too.
7070  *
7071  * This method firstly checks
7072  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
7073  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
7074  * an exception is thrown too.
7075  * 
7076  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
7077  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
7078  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
7079  */
7080 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
7081 {
7082   if(code.empty())
7083     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
7084   std::size_t sz=code.size();
7085   std::size_t n=sz/3;
7086   if(sz%3!=0)
7087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
7088   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7089   int nb=0;
7090   bool isNoPflUsed=true;
7091   for(std::size_t i=0;i<n;i++)
7092     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
7093       {
7094         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
7095         nb+=code[3*i+1];
7096         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
7097           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
7098         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
7099       }
7100   if(types.size()!=n)
7101     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
7102   if(isNoPflUsed)
7103     {
7104       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
7105         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
7106       if(types.size()==_types.size())
7107         return 0;
7108     }
7109   MCAuto<DataArrayInt> ret=DataArrayInt::New();
7110   ret->alloc(nb,1);
7111   int *retPtr=ret->getPointer();
7112   const int *connI=_nodal_connec_index->getConstPointer();
7113   const int *conn=_nodal_connec->getConstPointer();
7114   int nbOfCells=getNumberOfCells();
7115   const int *i=connI;
7116   int kk=0;
7117   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
7118     {
7119       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
7120       int offset=(int)std::distance(connI,i);
7121       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
7122       int nbOfCellsOfCurType=(int)std::distance(i,j);
7123       if(code[3*kk+2]==-1)
7124         for(int k=0;k<nbOfCellsOfCurType;k++)
7125           *retPtr++=k+offset;
7126       else
7127         {
7128           int idInIdsPerType=code[3*kk+2];
7129           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
7130             {
7131               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
7132               if(zePfl)
7133                 {
7134                   zePfl->checkAllocated();
7135                   if(zePfl->getNumberOfComponents()==1)
7136                     {
7137                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
7138                         {
7139                           if(*k>=0 && *k<nbOfCellsOfCurType)
7140                             *retPtr=(*k)+offset;
7141                           else
7142                             {
7143                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
7144                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
7145                               throw INTERP_KERNEL::Exception(oss.str());
7146                             }
7147                         }
7148                     }
7149                   else
7150                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
7151                 }
7152               else
7153                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
7154             }
7155           else
7156             {
7157               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
7158               oss << " should be in [0," << idsPerType.size() << ") !";
7159               throw INTERP_KERNEL::Exception(oss.str());
7160             }
7161         }
7162       i=j;
7163     }
7164   return ret.retn();
7165 }
7166
7167 /*!
7168  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
7169  * 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.
7170  * 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.
7171  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
7172  * 
7173  * \param [in] profile
7174  * \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.
7175  * \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,
7176  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
7177  * \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.
7178  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
7179  * \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
7180  */
7181 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
7182 {
7183   if(!profile)
7184     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
7185   if(profile->getNumberOfComponents()!=1)
7186     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
7187   checkConnectivityFullyDefined();
7188   const int *conn=_nodal_connec->getConstPointer();
7189   const int *connI=_nodal_connec_index->getConstPointer();
7190   int nbOfCells=getNumberOfCells();
7191   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7192   std::vector<int> typeRangeVals(1);
7193   for(const int *i=connI;i!=connI+nbOfCells;)
7194     {
7195       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7196       if(std::find(types.begin(),types.end(),curType)!=types.end())
7197         {
7198           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
7199         }
7200       types.push_back(curType);
7201       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7202       typeRangeVals.push_back((int)std::distance(connI,i));
7203     }
7204   //
7205   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
7206   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
7207   MCAuto<DataArrayInt> tmp0=castArr;
7208   MCAuto<DataArrayInt> tmp1=rankInsideCast;
7209   MCAuto<DataArrayInt> tmp2=castsPresent;
7210   //
7211   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7212   code.resize(3*nbOfCastsFinal);
7213   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
7214   std::vector< MCAuto<DataArrayInt> > idsPerType2;
7215   for(int i=0;i<nbOfCastsFinal;i++)
7216     {
7217       int castId=castsPresent->getIJ(i,0);
7218       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
7219       idsInPflPerType2.push_back(tmp3);
7220       code[3*i]=(int)types[castId];
7221       code[3*i+1]=tmp3->getNumberOfTuples();
7222       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7223       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
7224         {
7225           tmp4->copyStringInfoFrom(*profile);
7226           idsPerType2.push_back(tmp4);
7227           code[3*i+2]=(int)idsPerType2.size()-1;
7228         }
7229       else
7230         {
7231           code[3*i+2]=-1;
7232         }
7233     }
7234   std::size_t sz2=idsInPflPerType2.size();
7235   idsInPflPerType.resize(sz2);
7236   for(std::size_t i=0;i<sz2;i++)
7237     {
7238       DataArrayInt *locDa=idsInPflPerType2[i];
7239       locDa->incrRef();
7240       idsInPflPerType[i]=locDa;
7241     }
7242   std::size_t sz=idsPerType2.size();
7243   idsPerType.resize(sz);
7244   for(std::size_t i=0;i<sz;i++)
7245     {
7246       DataArrayInt *locDa=idsPerType2[i];
7247       locDa->incrRef();
7248       idsPerType[i]=locDa;
7249     }
7250 }
7251
7252 /*!
7253  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7254  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7255  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7256  * 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.
7257  */
7258 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7259 {
7260   checkFullyDefined();
7261   nM1LevMesh->checkFullyDefined();
7262   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7263     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7264   if(_coords!=nM1LevMesh->getCoords())
7265     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7266   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
7267   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
7268   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7269   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7270   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7271   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7272   tmp->setConnectivity(tmp0,tmp1);
7273   tmp->renumberCells(ret0->getConstPointer(),false);
7274   revDesc=tmp->getNodalConnectivity();
7275   revDescIndx=tmp->getNodalConnectivityIndex();
7276   DataArrayInt *ret=0;
7277   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7278     {
7279       int tmp2;
7280       ret->getMaxValue(tmp2);
7281       ret->decrRef();
7282       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7283       throw INTERP_KERNEL::Exception(oss.str());
7284     }
7285   nM1LevMeshIds=ret;
7286   //
7287   revDesc->incrRef();
7288   revDescIndx->incrRef();
7289   ret1->incrRef();
7290   ret0->incrRef();
7291   meshnM1Old2New=ret0;
7292   return ret1;
7293 }
7294
7295 /*!
7296  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7297  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7298  * in "Old to New" mode.
7299  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7300  *          this array using decrRef() as it is no more needed.
7301  *  \throw If the nodal connectivity of cells is not defined.
7302  */
7303 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7304 {
7305   checkConnectivityFullyDefined();
7306   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7307   renumberCells(ret->getConstPointer(),false);
7308   return ret.retn();
7309 }
7310
7311 /*!
7312  * This methods checks that cells are sorted by their types.
7313  * This method makes asumption (no check) that connectivity is correctly set before calling.
7314  */
7315 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7316 {
7317   checkFullyDefined();
7318   const int *conn=_nodal_connec->getConstPointer();
7319   const int *connI=_nodal_connec_index->getConstPointer();
7320   int nbOfCells=getNumberOfCells();
7321   std::set<INTERP_KERNEL::NormalizedCellType> types;
7322   for(const int *i=connI;i!=connI+nbOfCells;)
7323     {
7324       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7325       if(types.find(curType)!=types.end())
7326         return false;
7327       types.insert(curType);
7328       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7329     }
7330   return true;
7331 }
7332
7333 /*!
7334  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7335  * The geometric type order is specified by MED file.
7336  * 
7337  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7338  */
7339 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7340 {
7341   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7342 }
7343
7344 /*!
7345  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7346  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7347  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7348  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7349  */
7350 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7351 {
7352   checkFullyDefined();
7353   const int *conn=_nodal_connec->getConstPointer();
7354   const int *connI=_nodal_connec_index->getConstPointer();
7355   int nbOfCells=getNumberOfCells();
7356   if(nbOfCells==0)
7357     return true;
7358   int lastPos=-1;
7359   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7360   for(const int *i=connI;i!=connI+nbOfCells;)
7361     {
7362       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7363       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7364       if(isTypeExists!=orderEnd)
7365         {
7366           int pos=(int)std::distance(orderBg,isTypeExists);
7367           if(pos<=lastPos)
7368             return false;
7369           lastPos=pos;
7370           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7371         }
7372       else
7373         {
7374           if(sg.find(curType)==sg.end())
7375             {
7376               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7377               sg.insert(curType);
7378             }
7379           else
7380             return false;
7381         }
7382     }
7383   return true;
7384 }
7385
7386 /*!
7387  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7388  * 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
7389  * 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'.
7390  */
7391 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7392 {
7393   checkConnectivityFullyDefined();
7394   int nbOfCells=getNumberOfCells();
7395   const int *conn=_nodal_connec->getConstPointer();
7396   const int *connI=_nodal_connec_index->getConstPointer();
7397   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
7398   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
7399   tmpa->alloc(nbOfCells,1);
7400   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7401   tmpb->fillWithZero();
7402   int *tmp=tmpa->getPointer();
7403   int *tmp2=tmpb->getPointer();
7404   for(const int *i=connI;i!=connI+nbOfCells;i++)
7405     {
7406       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7407       if(where!=orderEnd)
7408         {
7409           int pos=(int)std::distance(orderBg,where);
7410           tmp2[pos]++;
7411           tmp[std::distance(connI,i)]=pos;
7412         }
7413       else
7414         {
7415           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7416           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7417           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7418           throw INTERP_KERNEL::Exception(oss.str());
7419         }
7420     }
7421   nbPerType=tmpb.retn();
7422   return tmpa.retn();
7423 }
7424
7425 /*!
7426  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7427  *
7428  * \return a new object containing the old to new correspondance.
7429  *
7430  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7431  */
7432 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7433 {
7434   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7435 }
7436
7437 /*!
7438  * 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.
7439  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7440  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7441  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7442  */
7443 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7444 {
7445   DataArrayInt *nbPerType=0;
7446   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7447   nbPerType->decrRef();
7448   return tmpa->buildPermArrPerLevel();
7449 }
7450
7451 /*!
7452  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7453  * The number of cells remains unchanged after the call of this method.
7454  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7455  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7456  *
7457  * \return the array giving the correspondance old to new.
7458  */
7459 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7460 {
7461   checkFullyDefined();
7462   computeTypes();
7463   const int *conn=_nodal_connec->getConstPointer();
7464   const int *connI=_nodal_connec_index->getConstPointer();
7465   int nbOfCells=getNumberOfCells();
7466   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7467   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7468     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7469       {
7470         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7471         types.push_back(curType);
7472         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7473       }
7474   DataArrayInt *ret=DataArrayInt::New();
7475   ret->alloc(nbOfCells,1);
7476   int *retPtr=ret->getPointer();
7477   std::fill(retPtr,retPtr+nbOfCells,-1);
7478   int newCellId=0;
7479   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7480     {
7481       for(const int *i=connI;i!=connI+nbOfCells;i++)
7482         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7483           retPtr[std::distance(connI,i)]=newCellId++;
7484     }
7485   renumberCells(retPtr,false);
7486   return ret;
7487 }
7488
7489 /*!
7490  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7491  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7492  * This method makes asumption that connectivity is correctly set before calling.
7493  */
7494 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7495 {
7496   checkConnectivityFullyDefined();
7497   const int *conn=_nodal_connec->getConstPointer();
7498   const int *connI=_nodal_connec_index->getConstPointer();
7499   int nbOfCells=getNumberOfCells();
7500   std::vector<MEDCouplingUMesh *> ret;
7501   for(const int *i=connI;i!=connI+nbOfCells;)
7502     {
7503       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7504       int beginCellId=(int)std::distance(connI,i);
7505       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7506       int endCellId=(int)std::distance(connI,i);
7507       int sz=endCellId-beginCellId;
7508       int *cells=new int[sz];
7509       for(int j=0;j<sz;j++)
7510         cells[j]=beginCellId+j;
7511       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7512       delete [] cells;
7513       ret.push_back(m);
7514     }
7515   return ret;
7516 }
7517
7518 /*!
7519  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7520  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7521  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7522  *
7523  * \return a newly allocated instance, that the caller must manage.
7524  * \throw If \a this contains more than one geometric type.
7525  * \throw If the nodal connectivity of \a this is not fully defined.
7526  * \throw If the internal data is not coherent.
7527  */
7528 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7529 {
7530   checkConnectivityFullyDefined();
7531   if(_types.size()!=1)
7532     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7533   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7534   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7535   ret->setCoords(getCoords());
7536   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7537   if(retC)
7538     {
7539       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7540       retC->setNodalConnectivity(c);
7541     }
7542   else
7543     {
7544       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7545       if(!retD)
7546         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7547       DataArrayInt *c=0,*ci=0;
7548       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7549       MCAuto<DataArrayInt> cs(c),cis(ci);
7550       retD->setNodalConnectivity(cs,cis);
7551     }
7552   return ret.retn();
7553 }
7554
7555 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7556 {
7557   checkConnectivityFullyDefined();
7558   if(_types.size()!=1)
7559     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7560   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7561   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7562   if(cm.isDynamic())
7563     {
7564       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7565       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7566       throw INTERP_KERNEL::Exception(oss.str());
7567     }
7568   int nbCells=getNumberOfCells();
7569   int typi=(int)typ;
7570   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7571   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7572   int *outPtr=connOut->getPointer();
7573   const int *conn=_nodal_connec->begin();
7574   const int *connI=_nodal_connec_index->begin();
7575   nbNodesPerCell++;
7576   for(int i=0;i<nbCells;i++,connI++)
7577     {
7578       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7579         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7580       else
7581         {
7582           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 << ") !";
7583           throw INTERP_KERNEL::Exception(oss.str());
7584         }
7585     }
7586   return connOut.retn();
7587 }
7588
7589 /*!
7590  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7591  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7592  * \param nodalConn
7593  * \param nodalConnI
7594  */
7595 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7596 {
7597   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
7598   checkConnectivityFullyDefined();
7599   if(_types.size()!=1)
7600     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7601   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7602   if(lgth<nbCells)
7603     throw INTERP_KERNEL::Exception(msg0);
7604   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7605   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7606   int *cp(c->getPointer()),*cip(ci->getPointer());
7607   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7608   cip[0]=0;
7609   for(int i=0;i<nbCells;i++,cip++,incip++)
7610     {
7611       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7612       int delta(stop-strt);
7613       if(delta>=1)
7614         {
7615           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7616             cp=std::copy(incp+strt,incp+stop,cp);
7617           else
7618             throw INTERP_KERNEL::Exception(msg0);
7619         }
7620       else
7621         throw INTERP_KERNEL::Exception(msg0);
7622       cip[1]=cip[0]+delta;
7623     }
7624   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7625 }
7626
7627 /*!
7628  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7629  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7630  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7631  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7632  * are not used here to avoid the build of big permutation array.
7633  *
7634  * \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
7635  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7636  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7637  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7638  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7639  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7640  * \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
7641  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7642  */
7643 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7644                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7645                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7646 {
7647   std::vector<const MEDCouplingUMesh *> ms2;
7648   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7649     if(*it)
7650       {
7651         (*it)->checkConnectivityFullyDefined();
7652         ms2.push_back(*it);
7653       }
7654   if(ms2.empty())
7655     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7656   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7657   int meshDim=ms2[0]->getMeshDimension();
7658   std::vector<const MEDCouplingUMesh *> m1ssm;
7659   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
7660   //
7661   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7662   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
7663   int fake=0,rk=0;
7664   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7665   ret1->alloc(0,1); ret2->alloc(0,1);
7666   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7667     {
7668       if(meshDim!=(*it)->getMeshDimension())
7669         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7670       if(refCoo!=(*it)->getCoords())
7671         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7672       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7673       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7674       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
7675       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7676         {
7677           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7678           m1ssmSingleAuto.push_back(singleCell);
7679           m1ssmSingle.push_back(singleCell);
7680           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7681         }
7682     }
7683   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7684   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7685   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7686   for(std::size_t i=0;i<m1ssm.size();i++)
7687     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7688   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7689   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7690   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7691   return ret0.retn();
7692 }
7693
7694 /*!
7695  * This method returns a newly created DataArrayInt instance.
7696  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7697  */
7698 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7699 {
7700   checkFullyDefined();
7701   const int *conn=_nodal_connec->getConstPointer();
7702   const int *connIndex=_nodal_connec_index->getConstPointer();
7703   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7704   for(const int *w=begin;w!=end;w++)
7705     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7706       ret->pushBackSilent(*w);
7707   return ret.retn();
7708 }
7709
7710 /*!
7711  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7712  * are in [0:getNumberOfCells())
7713  */
7714 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7715 {
7716   checkFullyDefined();
7717   const int *conn=_nodal_connec->getConstPointer();
7718   const int *connI=_nodal_connec_index->getConstPointer();
7719   int nbOfCells=getNumberOfCells();
7720   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7721   int *tmp=new int[nbOfCells];
7722   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7723     {
7724       int j=0;
7725       for(const int *i=connI;i!=connI+nbOfCells;i++)
7726         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7727           tmp[std::distance(connI,i)]=j++;
7728     }
7729   DataArrayInt *ret=DataArrayInt::New();
7730   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7731   ret->copyStringInfoFrom(*da);
7732   int *retPtr=ret->getPointer();
7733   const int *daPtr=da->getConstPointer();
7734   int nbOfElems=da->getNbOfElems();
7735   for(int k=0;k<nbOfElems;k++)
7736     retPtr[k]=tmp[daPtr[k]];
7737   delete [] tmp;
7738   return ret;
7739 }
7740
7741 /*!
7742  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7743  * This method \b works \b for mesh sorted by type.
7744  * cells whose ids is in 'idsPerGeoType' array.
7745  * This method conserves coords and name of mesh.
7746  */
7747 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7748 {
7749   std::vector<int> code=getDistributionOfTypes();
7750   std::size_t nOfTypesInThis=code.size()/3;
7751   int sz=0,szOfType=0;
7752   for(std::size_t i=0;i<nOfTypesInThis;i++)
7753     {
7754       if(code[3*i]!=type)
7755         sz+=code[3*i+1];
7756       else
7757         szOfType=code[3*i+1];
7758     }
7759   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7760     if(*work<0 || *work>=szOfType)
7761       {
7762         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7763         oss << ". It should be in [0," << szOfType << ") !";
7764         throw INTERP_KERNEL::Exception(oss.str());
7765       }
7766   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7767   int *idsPtr=idsTokeep->getPointer();
7768   int offset=0;
7769   for(std::size_t i=0;i<nOfTypesInThis;i++)
7770     {
7771       if(code[3*i]!=type)
7772         for(int j=0;j<code[3*i+1];j++)
7773           *idsPtr++=offset+j;
7774       else
7775         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7776       offset+=code[3*i+1];
7777     }
7778   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7779   ret->copyTinyInfoFrom(this);
7780   return ret.retn();
7781 }
7782
7783 /*!
7784  * This method returns a vector of size 'this->getNumberOfCells()'.
7785  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7786  */
7787 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7788 {
7789   int ncell=getNumberOfCells();
7790   std::vector<bool> ret(ncell);
7791   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7792   const int *c=getNodalConnectivity()->getConstPointer();
7793   for(int i=0;i<ncell;i++)
7794     {
7795       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7796       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7797       ret[i]=cm.isQuadratic();
7798     }
7799   return ret;
7800 }
7801
7802 /*!
7803  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7804  */
7805 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7806 {
7807   if(other->getType()!=UNSTRUCTURED)
7808     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7809   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7810   return MergeUMeshes(this,otherC);
7811 }
7812
7813 /*!
7814  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7815  * computed by averaging coordinates of cell nodes, so this method is not a right
7816  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7817  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7818  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7819  *          components. The caller is to delete this array using decrRef() as it is
7820  *          no more needed.
7821  *  \throw If the coordinates array is not set.
7822  *  \throw If the nodal connectivity of cells is not defined.
7823  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7824  */
7825 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
7826 {
7827   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7828   int spaceDim=getSpaceDimension();
7829   int nbOfCells=getNumberOfCells();
7830   ret->alloc(nbOfCells,spaceDim);
7831   ret->copyStringInfoFrom(*getCoords());
7832   double *ptToFill=ret->getPointer();
7833   const int *nodal=_nodal_connec->getConstPointer();
7834   const int *nodalI=_nodal_connec_index->getConstPointer();
7835   const double *coor=_coords->getConstPointer();
7836   for(int i=0;i<nbOfCells;i++)
7837     {
7838       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7839       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7840       ptToFill+=spaceDim;
7841     }
7842   return ret.retn();
7843 }
7844
7845 /*!
7846  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7847  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
7848  * 
7849  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7850  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7851  * 
7852  * \sa MEDCouplingUMesh::computeCellCenterOfMass
7853  * \throw If \a this is not fully defined (coordinates and connectivity)
7854  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7855  */
7856 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7857 {
7858   checkFullyDefined();
7859   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7860   int spaceDim=getSpaceDimension();
7861   int nbOfCells=getNumberOfCells();
7862   int nbOfNodes=getNumberOfNodes();
7863   ret->alloc(nbOfCells,spaceDim);
7864   double *ptToFill=ret->getPointer();
7865   const int *nodal=_nodal_connec->getConstPointer();
7866   const int *nodalI=_nodal_connec_index->getConstPointer();
7867   const double *coor=_coords->getConstPointer();
7868   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7869     {
7870       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7871       std::fill(ptToFill,ptToFill+spaceDim,0.);
7872       if(type!=INTERP_KERNEL::NORM_POLYHED)
7873         {
7874           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7875             {
7876               if(*conn>=0 && *conn<nbOfNodes)
7877                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7878               else
7879                 {
7880                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7881                   throw INTERP_KERNEL::Exception(oss.str());
7882                 }
7883             }
7884           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7885           if(nbOfNodesInCell>0)
7886             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7887           else
7888             {
7889               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7890               throw INTERP_KERNEL::Exception(oss.str());
7891             }
7892         }
7893       else
7894         {
7895           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7896           s.erase(-1);
7897           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7898             {
7899               if(*it>=0 && *it<nbOfNodes)
7900                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7901               else
7902                 {
7903                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7904                   throw INTERP_KERNEL::Exception(oss.str());
7905                 }
7906             }
7907           if(!s.empty())
7908             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7909           else
7910             {
7911               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7912               throw INTERP_KERNEL::Exception(oss.str());
7913             }
7914         }
7915     }
7916   return ret.retn();
7917 }
7918
7919 /*!
7920  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7921  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7922  * are specified via an array of cell ids. 
7923  *  \warning Validity of the specified cell ids is not checked! 
7924  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7925  *  \param [in] begin - an array of cell ids of interest.
7926  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7927  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7928  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7929  *          caller is to delete this array using decrRef() as it is no more needed. 
7930  *  \throw If the coordinates array is not set.
7931  *  \throw If the nodal connectivity of cells is not defined.
7932  *
7933  *  \if ENABLE_EXAMPLES
7934  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7935  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7936  *  \endif
7937  */
7938 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7939 {
7940   DataArrayDouble *ret=DataArrayDouble::New();
7941   int spaceDim=getSpaceDimension();
7942   int nbOfTuple=(int)std::distance(begin,end);
7943   ret->alloc(nbOfTuple,spaceDim);
7944   double *ptToFill=ret->getPointer();
7945   double *tmp=new double[spaceDim];
7946   const int *nodal=_nodal_connec->getConstPointer();
7947   const int *nodalI=_nodal_connec_index->getConstPointer();
7948   const double *coor=_coords->getConstPointer();
7949   for(const int *w=begin;w!=end;w++)
7950     {
7951       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7952       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7953       ptToFill+=spaceDim;
7954     }
7955   delete [] tmp;
7956   return ret;
7957 }
7958
7959 /*!
7960  * 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".
7961  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7962  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7963  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7964  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7965  * 
7966  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7967  * \throw If spaceDim!=3 or meshDim!=2.
7968  * \throw If connectivity of \a this is invalid.
7969  * \throw If connectivity of a cell in \a this points to an invalid node.
7970  */
7971 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7972 {
7973   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
7974   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7975   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7976     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7977   ret->alloc(nbOfCells,4);
7978   double *retPtr(ret->getPointer());
7979   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7980   const double *coor(_coords->begin());
7981   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7982     {
7983       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7984       if(nodalI[1]-nodalI[0]>=3)
7985         {
7986           for(int j=0;j<3;j++)
7987             {
7988               int nodeId(nodal[nodalI[0]+1+j]);
7989               if(nodeId>=0 && nodeId<nbOfNodes)
7990                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7991               else
7992                 {
7993                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7994                   throw INTERP_KERNEL::Exception(oss.str());
7995                 }
7996             }
7997         }
7998       else
7999         {
8000           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
8001           throw INTERP_KERNEL::Exception(oss.str());
8002         }
8003       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
8004       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
8005     }
8006   return ret.retn();
8007 }
8008
8009 /*!
8010  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
8011  * 
8012  */
8013 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
8014 {
8015   if(!da)
8016     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
8017   da->checkAllocated();
8018   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
8019   ret->setCoords(da);
8020   int nbOfTuples=da->getNumberOfTuples();
8021   MCAuto<DataArrayInt> c=DataArrayInt::New();
8022   MCAuto<DataArrayInt> cI=DataArrayInt::New();
8023   c->alloc(2*nbOfTuples,1);
8024   cI->alloc(nbOfTuples+1,1);
8025   int *cp=c->getPointer();
8026   int *cip=cI->getPointer();
8027   *cip++=0;
8028   for(int i=0;i<nbOfTuples;i++)
8029     {
8030       *cp++=INTERP_KERNEL::NORM_POINT1;
8031       *cp++=i;
8032       *cip++=2*(i+1);
8033     }
8034   ret->setConnectivity(c,cI,true);
8035   return ret.retn();
8036 }
8037 /*!
8038  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
8039  * Cells and nodes of
8040  * the first mesh precede cells and nodes of the second mesh within the result mesh.
8041  *  \param [in] mesh1 - the first mesh.
8042  *  \param [in] mesh2 - the second mesh.
8043  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8044  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8045  *          is no more needed.
8046  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
8047  *  \throw If the coordinates array is not set in none of the meshes.
8048  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
8049  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
8050  */
8051 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
8052 {
8053   std::vector<const MEDCouplingUMesh *> tmp(2);
8054   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
8055   return MergeUMeshes(tmp);
8056 }
8057
8058 /*!
8059  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
8060  * Cells and nodes of
8061  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
8062  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
8063  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8064  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8065  *          is no more needed.
8066  *  \throw If \a a.size() == 0.
8067  *  \throw If \a a[ *i* ] == NULL.
8068  *  \throw If the coordinates array is not set in none of the meshes.
8069  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
8070  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8071  */
8072 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const std::vector<const MEDCouplingUMesh *>& a)
8073 {
8074   std::size_t sz=a.size();
8075   if(sz==0)
8076     return MergeUMeshesLL(a);
8077   for(std::size_t ii=0;ii<sz;ii++)
8078     if(!a[ii])
8079       {
8080         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
8081         throw INTERP_KERNEL::Exception(oss.str());
8082       }
8083   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
8084   std::vector< const MEDCouplingUMesh * > aa(sz);
8085   int spaceDim=-3;
8086   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
8087     {
8088       const MEDCouplingUMesh *cur=a[i];
8089       const DataArrayDouble *coo=cur->getCoords();
8090       if(coo)
8091         spaceDim=coo->getNumberOfComponents();
8092     }
8093   if(spaceDim==-3)
8094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
8095   for(std::size_t i=0;i<sz;i++)
8096     {
8097       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
8098       aa[i]=bb[i];
8099     }
8100   return MergeUMeshesLL(aa);
8101 }
8102
8103 /// @cond INTERNAL
8104
8105 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(const std::vector<const MEDCouplingUMesh *>& a)
8106 {
8107   if(a.empty())
8108     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
8109   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
8110   int meshDim=(*it)->getMeshDimension();
8111   int nbOfCells=(*it)->getNumberOfCells();
8112   int meshLgth=(*it++)->getNodalConnectivityArrayLen();
8113   for(;it!=a.end();it++)
8114     {
8115       if(meshDim!=(*it)->getMeshDimension())
8116         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
8117       nbOfCells+=(*it)->getNumberOfCells();
8118       meshLgth+=(*it)->getNodalConnectivityArrayLen();
8119     }
8120   std::vector<const MEDCouplingPointSet *> aps(a.size());
8121   std::copy(a.begin(),a.end(),aps.begin());
8122   MCAuto<DataArrayDouble> pts=MergeNodesArray(aps);
8123   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
8124   ret->setCoords(pts);
8125   MCAuto<DataArrayInt> c=DataArrayInt::New();
8126   c->alloc(meshLgth,1);
8127   int *cPtr=c->getPointer();
8128   MCAuto<DataArrayInt> cI=DataArrayInt::New();
8129   cI->alloc(nbOfCells+1,1);
8130   int *cIPtr=cI->getPointer();
8131   *cIPtr++=0;
8132   int offset=0;
8133   int offset2=0;
8134   for(it=a.begin();it!=a.end();it++)
8135     {
8136       int curNbOfCell=(*it)->getNumberOfCells();
8137       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
8138       const int *curC=(*it)->_nodal_connec->getConstPointer();
8139       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
8140       for(int j=0;j<curNbOfCell;j++)
8141         {
8142           const int *src=curC+curCI[j];
8143           *cPtr++=*src++;
8144           for(;src!=curC+curCI[j+1];src++,cPtr++)
8145             {
8146               if(*src!=-1)
8147                 *cPtr=*src+offset2;
8148               else
8149                 *cPtr=-1;
8150             }
8151         }
8152       offset+=curCI[curNbOfCell];
8153       offset2+=(*it)->getNumberOfNodes();
8154     }
8155   //
8156   ret->setConnectivity(c,cI,true);
8157   return ret.retn();
8158 }
8159
8160 /// @endcond
8161
8162 /*!
8163  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
8164  * dimension and sharing the node coordinates array.
8165  * All cells of the first mesh precede all cells of the second mesh
8166  * within the result mesh. 
8167  *  \param [in] mesh1 - the first mesh.
8168  *  \param [in] mesh2 - the second mesh.
8169  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8170  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8171  *          is no more needed.
8172  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
8173  *  \throw If the meshes do not share the node coordinates array.
8174  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
8175  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
8176  */
8177 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
8178 {
8179   std::vector<const MEDCouplingUMesh *> tmp(2);
8180   tmp[0]=mesh1; tmp[1]=mesh2;
8181   return MergeUMeshesOnSameCoords(tmp);
8182 }
8183
8184 /*!
8185  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8186  * dimension and sharing the node coordinates array.
8187  * All cells of the *i*-th mesh precede all cells of the
8188  * (*i*+1)-th mesh within the result mesh.
8189  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8190  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8191  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8192  *          is no more needed.
8193  *  \throw If \a a.size() == 0.
8194  *  \throw If \a a[ *i* ] == NULL.
8195  *  \throw If the meshes do not share the node coordinates array.
8196  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
8197  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8198  */
8199 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
8200 {
8201   if(meshes.empty())
8202     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
8203   for(std::size_t ii=0;ii<meshes.size();ii++)
8204     if(!meshes[ii])
8205       {
8206         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
8207         throw INTERP_KERNEL::Exception(oss.str());
8208       }
8209   const DataArrayDouble *coords=meshes.front()->getCoords();
8210   int meshDim=meshes.front()->getMeshDimension();
8211   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8212   int meshLgth=0;
8213   int meshIndexLgth=0;
8214   for(;iter!=meshes.end();iter++)
8215     {
8216       if(coords!=(*iter)->getCoords())
8217         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8218       if(meshDim!=(*iter)->getMeshDimension())
8219         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8220       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
8221       meshIndexLgth+=(*iter)->getNumberOfCells();
8222     }
8223   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
8224   nodal->alloc(meshLgth,1);
8225   int *nodalPtr=nodal->getPointer();
8226   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
8227   nodalIndex->alloc(meshIndexLgth+1,1);
8228   int *nodalIndexPtr=nodalIndex->getPointer();
8229   int offset=0;
8230   for(iter=meshes.begin();iter!=meshes.end();iter++)
8231     {
8232       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8233       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8234       int nbOfCells=(*iter)->getNumberOfCells();
8235       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
8236       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8237       if(iter!=meshes.begin())
8238         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8239       else
8240         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8241       offset+=meshLgth2;
8242     }
8243   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8244   ret->setName("merge");
8245   ret->setMeshDimension(meshDim);
8246   ret->setConnectivity(nodal,nodalIndex,true);
8247   ret->setCoords(coords);
8248   return ret;
8249 }
8250
8251 /*!
8252  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8253  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8254  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8255  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8256  * New" mode are returned for each input mesh.
8257  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8258  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8259  *          valid values [0,1,2], see zipConnectivityTraducer().
8260  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8261  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8262  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8263  *          no more needed.
8264  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8265  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8266  *          is no more needed.
8267  *  \throw If \a meshes.size() == 0.
8268  *  \throw If \a meshes[ *i* ] == NULL.
8269  *  \throw If the meshes do not share the node coordinates array.
8270  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8271  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8272  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8273  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8274  */
8275 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8276 {
8277   //All checks are delegated to MergeUMeshesOnSameCoords
8278   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8279   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8280   corr.resize(meshes.size());
8281   std::size_t nbOfMeshes=meshes.size();
8282   int offset=0;
8283   const int *o2nPtr=o2n->getConstPointer();
8284   for(std::size_t i=0;i<nbOfMeshes;i++)
8285     {
8286       DataArrayInt *tmp=DataArrayInt::New();
8287       int curNbOfCells=meshes[i]->getNumberOfCells();
8288       tmp->alloc(curNbOfCells,1);
8289       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8290       offset+=curNbOfCells;
8291       tmp->setName(meshes[i]->getName());
8292       corr[i]=tmp;
8293     }
8294   return ret.retn();
8295 }
8296
8297 /*!
8298  * Makes all given meshes share the nodal connectivity array. The common connectivity
8299  * array is created by concatenating the connectivity arrays of all given meshes. All
8300  * the given meshes must be of the same space dimension but dimension of cells **can
8301  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8302  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8303  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8304  *  \param [in,out] meshes - a vector of meshes to update.
8305  *  \throw If any of \a meshes is NULL.
8306  *  \throw If the coordinates array is not set in any of \a meshes.
8307  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8308  *  \throw If \a meshes are of different space dimension.
8309  */
8310 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8311 {
8312   std::size_t sz=meshes.size();
8313   if(sz==0 || sz==1)
8314     return;
8315   std::vector< const DataArrayDouble * > coords(meshes.size());
8316   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8317   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8318     {
8319       if((*it))
8320         {
8321           (*it)->checkConnectivityFullyDefined();
8322           const DataArrayDouble *coo=(*it)->getCoords();
8323           if(coo)
8324             *it2=coo;
8325           else
8326             {
8327               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8328               oss << " has no coordinate array defined !";
8329               throw INTERP_KERNEL::Exception(oss.str());
8330             }
8331         }
8332       else
8333         {
8334           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8335           oss << " is null !";
8336           throw INTERP_KERNEL::Exception(oss.str());
8337         }
8338     }
8339   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8340   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8341   int offset=(*it)->getNumberOfNodes();
8342   (*it++)->setCoords(res);
8343   for(;it!=meshes.end();it++)
8344     {
8345       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8346       (*it)->setCoords(res);
8347       (*it)->shiftNodeNumbersInConn(offset);
8348       offset+=oldNumberOfNodes;
8349     }
8350 }
8351
8352 /*!
8353  * Merges nodes coincident with a given precision within all given meshes that share
8354  * the nodal connectivity array. The given meshes **can be of different** mesh
8355  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8356  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8357  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8358  *  \param [in,out] meshes - a vector of meshes to update.
8359  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8360  *  \throw If any of \a meshes is NULL.
8361  *  \throw If the \a meshes do not share the same node coordinates array.
8362  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8363  */
8364 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8365 {
8366   if(meshes.empty())
8367     return ;
8368   std::set<const DataArrayDouble *> s;
8369   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8370     {
8371       if(*it)
8372         s.insert((*it)->getCoords());
8373       else
8374         {
8375           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 !";
8376           throw INTERP_KERNEL::Exception(oss.str());
8377         }
8378     }
8379   if(s.size()!=1)
8380     {
8381       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 !";
8382       throw INTERP_KERNEL::Exception(oss.str());
8383     }
8384   const DataArrayDouble *coo=*(s.begin());
8385   if(!coo)
8386     return;
8387   //
8388   DataArrayInt *comm,*commI;
8389   coo->findCommonTuples(eps,-1,comm,commI);
8390   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
8391   int oldNbOfNodes=coo->getNumberOfTuples();
8392   int newNbOfNodes;
8393   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8394   if(oldNbOfNodes==newNbOfNodes)
8395     return ;
8396   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8397   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8398     {
8399       (*it)->renumberNodesInConn(o2n->getConstPointer());
8400       (*it)->setCoords(newCoords);
8401     } 
8402 }
8403
8404 /*!
8405  * 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.
8406  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8407  * \param isQuad specifies the policy of connectivity.
8408  * @ret in/out parameter in which the result will be append
8409  */
8410 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8411 {
8412   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8413   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8414   ret.push_back(cm.getExtrudedType());
8415   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8416   switch(flatType)
8417   {
8418     case INTERP_KERNEL::NORM_POINT1:
8419       {
8420         ret.push_back(connBg[1]);
8421         ret.push_back(connBg[1]+nbOfNodesPerLev);
8422         break;
8423       }
8424     case INTERP_KERNEL::NORM_SEG2:
8425       {
8426         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8427         ret.insert(ret.end(),conn,conn+4);
8428         break;
8429       }
8430     case INTERP_KERNEL::NORM_SEG3:
8431       {
8432         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8433         ret.insert(ret.end(),conn,conn+8);
8434         break;
8435       }
8436     case INTERP_KERNEL::NORM_QUAD4:
8437       {
8438         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8439         ret.insert(ret.end(),conn,conn+8);
8440         break;
8441       }
8442     case INTERP_KERNEL::NORM_TRI3:
8443       {
8444         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8445         ret.insert(ret.end(),conn,conn+6);
8446         break;
8447       }
8448     case INTERP_KERNEL::NORM_TRI6:
8449       {
8450         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,
8451           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8452         ret.insert(ret.end(),conn,conn+15);
8453         break;
8454       }
8455     case INTERP_KERNEL::NORM_QUAD8:
8456       {
8457         int conn[20]={
8458           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8459           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8460           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8461         };
8462         ret.insert(ret.end(),conn,conn+20);
8463         break;
8464       }
8465     case INTERP_KERNEL::NORM_POLYGON:
8466       {
8467         std::back_insert_iterator< std::vector<int> > ii(ret);
8468         std::copy(connBg+1,connEnd,ii);
8469         *ii++=-1;
8470         std::reverse_iterator<const int *> rConnBg(connEnd);
8471         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8472         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8473         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8474         for(std::size_t i=0;i<nbOfRadFaces;i++)
8475           {
8476             *ii++=-1;
8477             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8478             std::copy(conn,conn+4,ii);
8479           }
8480         break;
8481       }
8482     default:
8483       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8484   }
8485 }
8486
8487 /*!
8488  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8489  */
8490 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8491 {
8492   std::size_t i, ip1;
8493   double v[3]={0.,0.,0.};
8494   std::size_t sz=std::distance(begin,end);
8495   if(isQuadratic)
8496     sz/=2;
8497   for(i=0;i<sz;i++)
8498     {
8499       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];
8500       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8501       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8502     }
8503   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8504
8505   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8506   // SEG3 forming a circle):
8507   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8508     {
8509       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8510       for(std::size_t j=0;j<sz;j++)
8511         {
8512           if (j%2)  // current point i is quadratic, next point i+1 is standard
8513             {
8514               i = sz+j;
8515               ip1 = (j+1)%sz; // ip1 = "i+1"
8516             }
8517           else      // current point i is standard, next point i+1 is quadratic
8518             {
8519               i = j;
8520               ip1 = j+sz;
8521             }
8522           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8523           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8524           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8525         }
8526       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8527     }
8528   return (ret>0.);
8529 }
8530
8531 /*!
8532  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8533  */
8534 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8535 {
8536   std::vector<std::pair<int,int> > edges;
8537   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8538   const int *bgFace=begin;
8539   for(std::size_t i=0;i<nbOfFaces;i++)
8540     {
8541       const int *endFace=std::find(bgFace+1,end,-1);
8542       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8543       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8544         {
8545           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8546           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8547             return false;
8548           edges.push_back(p1);
8549         }
8550       bgFace=endFace+1;
8551     }
8552   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8553 }
8554
8555 /*!
8556  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8557  */
8558 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8559 {
8560   double vec0[3],vec1[3];
8561   std::size_t sz=std::distance(begin,end);
8562   if(sz%2!=0)
8563     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8564   int nbOfNodes=(int)sz/2;
8565   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8566   const double *pt0=coords+3*begin[0];
8567   const double *pt1=coords+3*begin[nbOfNodes];
8568   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8569   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8570 }
8571
8572 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8573 {
8574   std::size_t sz=std::distance(begin,end);
8575   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8576   std::size_t nbOfNodes(sz/2);
8577   std::copy(begin,end,(int *)tmp);
8578   for(std::size_t j=1;j<nbOfNodes;j++)
8579     {
8580       begin[j]=tmp[nbOfNodes-j];
8581       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8582     }
8583 }
8584
8585 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8586 {
8587   std::size_t sz=std::distance(begin,end);
8588   if(sz!=4)
8589     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
8590   double vec0[3],vec1[3];
8591   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8592   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]; 
8593   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;
8594 }
8595
8596 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8597 {
8598   std::size_t sz=std::distance(begin,end);
8599   if(sz!=5)
8600     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
8601   double vec0[3];
8602   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8603   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8604   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8605 }
8606
8607 /*!
8608  * 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 ) 
8609  * 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
8610  * a 2D space.
8611  *
8612  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8613  * \param [in] coords the coordinates with nb of components exactly equal to 3
8614  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8615  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8616  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8617  */
8618 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8619 {
8620   int nbFaces=std::count(begin+1,end,-1)+1;
8621   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8622   double *vPtr=v->getPointer();
8623   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8624   double *pPtr=p->getPointer();
8625   const int *stFaceConn=begin+1;
8626   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8627     {
8628       const int *endFaceConn=std::find(stFaceConn,end,-1);
8629       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8630       stFaceConn=endFaceConn+1;
8631     }
8632   pPtr=p->getPointer(); vPtr=v->getPointer();
8633   DataArrayInt *comm1=0,*commI1=0;
8634   v->findCommonTuples(eps,-1,comm1,commI1);
8635   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8636   const int *comm1Ptr=comm1->getConstPointer();
8637   const int *commI1Ptr=commI1->getConstPointer();
8638   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8639   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8640   //
8641   MCAuto<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8642   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8643   mm->finishInsertingCells();
8644   //
8645   for(int i=0;i<nbOfGrps1;i++)
8646     {
8647       int vecId=comm1Ptr[commI1Ptr[i]];
8648       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8649       DataArrayInt *comm2=0,*commI2=0;
8650       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8651       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8652       const int *comm2Ptr=comm2->getConstPointer();
8653       const int *commI2Ptr=commI2->getConstPointer();
8654       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8655       for(int j=0;j<nbOfGrps2;j++)
8656         {
8657           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8658             {
8659               res->insertAtTheEnd(begin,end);
8660               res->pushBackSilent(-1);
8661             }
8662           else
8663             {
8664               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8665               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
8666               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8667               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8668               MCAuto<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8669               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8670               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8671               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8672               const int *idsNodePtr=idsNode->getConstPointer();
8673               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];
8674               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8675               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8676               if(std::abs(norm)>eps)
8677                 {
8678                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8679                   mm3->rotate(center,vec,angle);
8680                 }
8681               mm3->changeSpaceDimension(2);
8682               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8683               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8684               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8685               int nbOfCells=mm4->getNumberOfCells();
8686               for(int k=0;k<nbOfCells;k++)
8687                 {
8688                   int l=0;
8689                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8690                     res->pushBackSilent(idsNodePtr[*work]);
8691                   res->pushBackSilent(-1);
8692                 }
8693             }
8694         }
8695     }
8696   res->popBackSilent();
8697 }
8698
8699 /*!
8700  * 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
8701  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8702  * 
8703  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8704  * \param [in] coords coordinates expected to have 3 components.
8705  * \param [in] begin start of the nodal connectivity of the face.
8706  * \param [in] end end of the nodal connectivity (excluded) of the face.
8707  * \param [out] v the normalized vector of size 3
8708  * \param [out] p the pos of plane
8709  */
8710 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8711 {
8712   std::size_t nbPoints=std::distance(begin,end);
8713   if(nbPoints<3)
8714     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8715   double vec[3]={0.,0.,0.};
8716   std::size_t j=0;
8717   bool refFound=false;
8718   for(;j<nbPoints-1 && !refFound;j++)
8719     {
8720       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8721       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8722       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8723       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8724       if(norm>eps)
8725         {
8726           refFound=true;
8727           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8728         }
8729     }
8730   for(std::size_t i=j;i<nbPoints-1;i++)
8731     {
8732       double curVec[3];
8733       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8734       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8735       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8736       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8737       if(norm<eps)
8738         continue;
8739       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8740       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];
8741       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8742       if(norm>eps)
8743         {
8744           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8745           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8746           return ;
8747         }
8748     }
8749   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8750 }
8751
8752 /*!
8753  * This method tries to obtain a well oriented polyhedron.
8754  * If the algorithm fails, an exception will be thrown.
8755  */
8756 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8757 {
8758   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8759   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8760   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8761   isPerm[0]=true;
8762   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8763   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8764   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8765   //
8766   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8767     {
8768       bgFace=begin;
8769       std::size_t smthChanged=0;
8770       for(std::size_t i=0;i<nbOfFaces;i++)
8771         {
8772           endFace=std::find(bgFace+1,end,-1);
8773           nbOfEdgesInFace=std::distance(bgFace,endFace);
8774           if(!isPerm[i])
8775             {
8776               bool b;
8777               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8778                 {
8779                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8780                   std::pair<int,int> p2(p1.second,p1.first);
8781                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8782                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8783                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8784                 }
8785               if(isPerm[i])
8786                 { 
8787                   if(!b)
8788                     std::reverse(bgFace+1,endFace);
8789                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8790                     {
8791                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8792                       std::pair<int,int> p2(p1.second,p1.first);
8793                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8794                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
8795                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8796                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
8797                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8798                       if(it!=edgesOK.end())
8799                         {
8800                           edgesOK.erase(it);
8801                           edgesFinished.push_back(p1);
8802                         }
8803                       else
8804                         edgesOK.push_back(p1);
8805                     }
8806                 }
8807             }
8808           bgFace=endFace+1;
8809         }
8810       if(smthChanged==0)
8811         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8812     }
8813   if(!edgesOK.empty())
8814     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8815   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8816     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8817       bgFace=begin;
8818       for(std::size_t i=0;i<nbOfFaces;i++)
8819         {
8820           endFace=std::find(bgFace+1,end,-1);
8821           std::reverse(bgFace+1,endFace);
8822           bgFace=endFace+1;
8823         }
8824     }
8825 }
8826
8827 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8828 {
8829   int nbOfNodesExpected(skin->getNumberOfNodes());
8830   const int *n2oPtr(n2o->getConstPointer());
8831   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8832   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8833   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8834   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8835   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8836   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8837   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8838   if(nbOfNodesExpected<1)
8839     return ret.retn();
8840   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8841   *work++=n2oPtr[prevNode];
8842   for(int i=1;i<nbOfNodesExpected;i++)
8843     {
8844       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8845         {
8846           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8847           conn.erase(prevNode);
8848           if(conn.size()==1)
8849             {
8850               int curNode(*(conn.begin()));
8851               *work++=n2oPtr[curNode];
8852               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8853               shar.erase(prevCell);
8854               if(shar.size()==1)
8855                 {
8856                   prevCell=*(shar.begin());
8857                   prevNode=curNode;
8858                 }
8859               else
8860                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8861             }
8862           else
8863             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8864         }
8865       else
8866         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8867     }
8868   return ret.retn();
8869 }
8870
8871 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8872 {
8873   int nbOfNodesExpected(skin->getNumberOfNodes());
8874   int nbOfTurn(nbOfNodesExpected/2);
8875   const int *n2oPtr(n2o->getConstPointer());
8876   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8877   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8878   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8879   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8880   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8881   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8882   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8883   if(nbOfNodesExpected<1)
8884     return ret.retn();
8885   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8886   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8887   for(int i=1;i<nbOfTurn;i++)
8888     {
8889       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8890         {
8891           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8892           conn.erase(prevNode);
8893           if(conn.size()==1)
8894             {
8895               int curNode(*(conn.begin()));
8896               *work=n2oPtr[curNode];
8897               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8898               shar.erase(prevCell);
8899               if(shar.size()==1)
8900                 {
8901                   int curCell(*(shar.begin()));
8902                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8903                   prevCell=curCell;
8904                   prevNode=curNode;
8905                   work++;
8906                 }
8907               else
8908                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8909             }
8910           else
8911             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8912         }
8913       else
8914         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8915     }
8916   return ret.retn();
8917 }
8918
8919 /*!
8920  * This method makes the assumption spacedimension == meshdimension == 2.
8921  * This method works only for linear cells.
8922  * 
8923  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8924  */
8925 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8926 {
8927   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8928     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8929   MCAuto<MEDCouplingUMesh> skin(computeSkin());
8930   int oldNbOfNodes(skin->getNumberOfNodes());
8931   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
8932   int nbOfNodesExpected(skin->getNumberOfNodes());
8933   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8934   int nbCells(skin->getNumberOfCells());
8935   if(nbCells==nbOfNodesExpected)
8936     return buildUnionOf2DMeshLinear(skin,n2o);
8937   else if(2*nbCells==nbOfNodesExpected)
8938     return buildUnionOf2DMeshQuadratic(skin,n2o);
8939   else
8940     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8941 }
8942
8943 /*!
8944  * This method makes the assumption spacedimension == meshdimension == 3.
8945  * This method works only for linear cells.
8946  * 
8947  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8948  */
8949 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8950 {
8951   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8952     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8953   MCAuto<MEDCouplingUMesh> m=computeSkin();
8954   const int *conn=m->getNodalConnectivity()->getConstPointer();
8955   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8956   int nbOfCells=m->getNumberOfCells();
8957   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8958   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8959   if(nbOfCells<1)
8960     return ret.retn();
8961   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8962   for(int i=1;i<nbOfCells;i++)
8963     {
8964       *work++=-1;
8965       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8966     }
8967   return ret.retn();
8968 }
8969
8970 /*!
8971  * \brief Creates a graph of cell neighbors
8972  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8973  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8974  *  For example
8975  *  - index:  0 3 5 6 6
8976  *  - value:  1 2 3 2 3 3
8977  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8978  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8979  */
8980 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8981 {
8982   checkConnectivityFullyDefined();
8983
8984   int meshDim = this->getMeshDimension();
8985   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
8986   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
8987   this->getReverseNodalConnectivity(revConn,indexr);
8988   const int* indexr_ptr=indexr->getConstPointer();
8989   const int* revConn_ptr=revConn->getConstPointer();
8990
8991   const MEDCoupling::DataArrayInt* index;
8992   const MEDCoupling::DataArrayInt* conn;
8993   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8994   index=this->getNodalConnectivityIndex();
8995   int nbCells=this->getNumberOfCells();
8996   const int* index_ptr=index->getConstPointer();
8997   const int* conn_ptr=conn->getConstPointer();
8998
8999   //creating graph arcs (cell to cell relations)
9000   //arcs are stored in terms of (index,value) notation
9001   // 0 3 5 6 6
9002   // 1 2 3 2 3 3
9003   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
9004   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
9005
9006   //warning here one node have less than or equal effective number of cell with it
9007   //but cell could have more than effective nodes
9008   //because other equals nodes in other domain (with other global inode)
9009   std::vector <int> cell2cell_index(nbCells+1,0);
9010   std::vector <int> cell2cell;
9011   cell2cell.reserve(3*nbCells);
9012
9013   for (int icell=0; icell<nbCells;icell++)
9014     {
9015       std::map<int,int > counter;
9016       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
9017         {
9018           int inode=conn_ptr[iconn];
9019           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
9020             {
9021               int icell2=revConn_ptr[iconnr];
9022               std::map<int,int>::iterator iter=counter.find(icell2);
9023               if (iter!=counter.end()) (iter->second)++;
9024               else counter.insert(std::make_pair(icell2,1));
9025             }
9026         }
9027       for (std::map<int,int>::const_iterator iter=counter.begin();
9028            iter!=counter.end(); iter++)
9029         if (iter->second >= meshDim)
9030           {
9031             cell2cell_index[icell+1]++;
9032             cell2cell.push_back(iter->first);
9033           }
9034     }
9035   indexr->decrRef();
9036   revConn->decrRef();
9037   cell2cell_index[0]=0;
9038   for (int icell=0; icell<nbCells;icell++)
9039     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
9040
9041   //filling up index and value to create skylinearray structure
9042   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
9043   return array;
9044 }
9045
9046 /*!
9047  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
9048  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
9049  */
9050 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
9051 {
9052   double *w=zipFrmt;
9053   if(spaceDim==3)
9054     for(int i=0;i<nbOfNodesInCell;i++)
9055       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
9056   else if(spaceDim==2)
9057     {
9058       for(int i=0;i<nbOfNodesInCell;i++)
9059         {
9060           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
9061           *w++=0.;
9062         }
9063     }
9064   else
9065     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
9066 }
9067
9068 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
9069 {
9070   int nbOfCells=getNumberOfCells();
9071   if(nbOfCells<=0)
9072     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
9073   ofs << "  <" << getVTKDataSetType() << ">\n";
9074   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
9075   ofs << "      <PointData>\n" << pointData << std::endl;
9076   ofs << "      </PointData>\n";
9077   ofs << "      <CellData>\n" << cellData << std::endl;
9078   ofs << "      </CellData>\n";
9079   ofs << "      <Points>\n";
9080   if(getSpaceDimension()==3)
9081     _coords->writeVTK(ofs,8,"Points",byteData);
9082   else
9083     {
9084       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
9085       coo->writeVTK(ofs,8,"Points",byteData);
9086     }
9087   ofs << "      </Points>\n";
9088   ofs << "      <Cells>\n";
9089   const int *cPtr=_nodal_connec->getConstPointer();
9090   const int *cIPtr=_nodal_connec_index->getConstPointer();
9091   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
9092   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
9093   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
9094   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
9095   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
9096   int szFaceOffsets=0,szConn=0;
9097   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
9098     {
9099       *w2=cPtr[cIPtr[i]];
9100       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
9101         {
9102           *w1=-1;
9103           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
9104           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
9105         }
9106       else
9107         {
9108           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
9109           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
9110           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
9111           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
9112           w4=std::copy(c.begin(),c.end(),w4);
9113         }
9114     }
9115   types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
9116   types->writeVTK(ofs,8,"UInt8","types",byteData);
9117   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
9118   if(szFaceOffsets!=0)
9119     {//presence of Polyhedra
9120       connectivity->reAlloc(szConn);
9121       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
9122       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
9123       w1=faces->getPointer();
9124       for(int i=0;i<nbOfCells;i++)
9125         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
9126           {
9127             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
9128             *w1++=nbFaces;
9129             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
9130             for(int j=0;j<nbFaces;j++)
9131               {
9132                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
9133                 *w1++=(int)std::distance(w6,w5);
9134                 w1=std::copy(w6,w5,w1);
9135                 w6=w5+1;
9136               }
9137           }
9138       faces->writeVTK(ofs,8,"Int32","faces",byteData);
9139     }
9140   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
9141   ofs << "      </Cells>\n";
9142   ofs << "    </Piece>\n";
9143   ofs << "  </" << getVTKDataSetType() << ">\n";
9144 }
9145
9146 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
9147 {
9148   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
9149   if(_mesh_dim==-2)
9150     { stream << " Not set !"; return ; }
9151   stream << " Mesh dimension : " << _mesh_dim << ".";
9152   if(_mesh_dim==-1)
9153     return ;
9154   if(!_coords)
9155     { stream << " No coordinates set !"; return ; }
9156   if(!_coords->isAllocated())
9157     { stream << " Coordinates set but not allocated !"; return ; }
9158   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
9159   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
9160   if(!_nodal_connec_index)
9161     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
9162   if(!_nodal_connec_index->isAllocated())
9163     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
9164   int lgth=_nodal_connec_index->getNumberOfTuples();
9165   int cpt=_nodal_connec_index->getNumberOfComponents();
9166   if(cpt!=1 || lgth<1)
9167     return ;
9168   stream << std::endl << "Number of cells : " << lgth-1 << ".";
9169 }
9170
9171 std::string MEDCouplingUMesh::getVTKDataSetType() const
9172 {
9173   return std::string("UnstructuredGrid");
9174 }
9175
9176 std::string MEDCouplingUMesh::getVTKFileExtension() const
9177 {
9178   return std::string("vtu");
9179 }
9180
9181 /*!
9182  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
9183  * returns a result mesh constituted by polygons.
9184  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
9185  * all nodes from m2.
9186  * The meshes should be in 2D space. In
9187  * addition, returns two arrays mapping cells of the result mesh to cells of the input
9188  * meshes.
9189  *  \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
9190  *                      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)
9191  *  \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
9192  *                      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)
9193  *  \param [in] eps - precision used to detect coincident mesh entities.
9194  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
9195  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
9196  *         this array using decrRef() as it is no more needed.
9197  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
9198  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
9199  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
9200  *         any cell of \a m2. The caller is to delete this array using decrRef() as
9201  *         it is no more needed.  
9202  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
9203  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
9204  *         is no more needed.  
9205  *  \throw If the coordinates array is not set in any of the meshes.
9206  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
9207  *  \throw If any of the meshes is not a 2D mesh in 2D space.
9208  *
9209  *  \sa conformize2D, mergeNodes
9210  */
9211 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9212                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9213 {
9214   if(!m1 || !m2)
9215     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9216   m1->checkFullyDefined();
9217   m2->checkFullyDefined();
9218   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9219     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9220
9221   // Step 1: compute all edge intersections (new nodes)
9222   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9223   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9224   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9225   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9226   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9227                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9228                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9229   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9230   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9231   MCAuto<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9232
9233   // Step 2: re-order newly created nodes according to the ordering found in m2
9234   std::vector< std::vector<int> > intersectEdge2;
9235   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9236   subDiv2.clear(); dd5=0; dd6=0;
9237
9238   // Step 3:
9239   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9240   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9241   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9242                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9243
9244   // Step 4: Prepare final result:
9245   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9246   addCooDa->alloc((int)(addCoo.size())/2,2);
9247   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9248   MCAuto<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9249   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9250   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9251   std::vector<const DataArrayDouble *> coordss(4);
9252   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9253   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9254   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9255   MCAuto<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9256   MCAuto<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9257   MCAuto<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9258   MCAuto<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9259   ret->setConnectivity(conn,connI,true);
9260   ret->setCoords(coo);
9261   cellNb1=c1.retn(); cellNb2=c2.retn();
9262   return ret.retn();
9263 }
9264
9265 /// @cond INTERNAL
9266
9267 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9268 {
9269   if(candidates.empty())
9270     return false;
9271   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9272     {
9273       const std::vector<int>& pool(intersectEdge1[*it]);
9274       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9275       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9276         {
9277           retVal=*it+1;
9278           return true;
9279         }
9280       tmp[0]=stop; tmp[1]=start;
9281       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9282         {
9283           retVal=-*it-1;
9284           return true;
9285         }
9286     }
9287   return false;
9288 }
9289
9290 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,
9291                                      MCAuto<DataArrayInt>& idsInRetColinear, MCAuto<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9292 {
9293   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9294   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9295   int nCells(mesh1D->getNumberOfCells());
9296   if(nCells!=(int)intersectEdge2.size())
9297     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9298   const DataArrayDouble *coo2(mesh1D->getCoords());
9299   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9300   const double *coo2Ptr(coo2->begin());
9301   int offset1(coords1->getNumberOfTuples());
9302   int offset2(offset1+coo2->getNumberOfTuples());
9303   int offset3(offset2+addCoo.size()/2);
9304   std::vector<double> addCooQuad;
9305   MCAuto<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9306   int tmp[4],cicnt(0),kk(0);
9307   for(int i=0;i<nCells;i++)
9308     {
9309       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
9310       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9311       const std::vector<int>& subEdges(intersectEdge2[i]);
9312       int nbSubEdge(subEdges.size()/2);
9313       for(int j=0;j<nbSubEdge;j++,kk++)
9314         {
9315           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));
9316           MCAuto<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9317           INTERP_KERNEL::Edge *e2Ptr(e2);
9318           std::map<int,int>::const_iterator itm;
9319           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9320             {
9321               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9322               itm=mergedNodes.find(subEdges[2*j]);
9323               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9324               itm=mergedNodes.find(subEdges[2*j+1]);
9325               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9326               tmp[3]=offset3+(int)addCooQuad.size()/2;
9327               double tmp2[2];
9328               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9329               cicnt+=4;
9330               cOut->insertAtTheEnd(tmp,tmp+4);
9331               ciOut->pushBackSilent(cicnt);
9332             }
9333           else
9334             {
9335               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9336               itm=mergedNodes.find(subEdges[2*j]);
9337               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9338               itm=mergedNodes.find(subEdges[2*j+1]);
9339               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9340               cicnt+=3;
9341               cOut->insertAtTheEnd(tmp,tmp+3);
9342               ciOut->pushBackSilent(cicnt);
9343             }
9344           int tmp00;
9345           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9346             {
9347               idsInRetColinear->pushBackSilent(kk);
9348               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9349             }
9350         }
9351       e->decrRef();
9352     }
9353   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9354   ret->setConnectivity(cOut,ciOut,true);
9355   MCAuto<DataArrayDouble> arr3(DataArrayDouble::New());
9356   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9357   MCAuto<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9358   std::vector<const DataArrayDouble *> coordss(4);
9359   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9360   MCAuto<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9361   ret->setCoords(arr);
9362   return ret.retn();
9363 }
9364
9365 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9366 {
9367   std::vector<int> allEdges;
9368   for(const int *it2(descBg);it2!=descEnd;it2++)
9369     {
9370       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9371       if(*it2>0)
9372         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9373       else
9374         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9375     }
9376   std::size_t nb(allEdges.size());
9377   if(nb%2!=0)
9378     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9379   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9380   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9381   ret->setCoords(coords);
9382   ret->allocateCells(1);
9383   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9384   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9385     connOut[kk]=allEdges[2*kk];
9386   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9387   return ret.retn();
9388 }
9389
9390 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9391 {
9392   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9393   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9394   std::size_t ii(0);
9395   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9396   if(sz!=std::distance(descBg,descEnd))
9397     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9398   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9399   std::vector<int> allEdges,centers;
9400   const double *coordsPtr(coords->begin());
9401   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9402   int offset(coords->getNumberOfTuples());
9403   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9404     {
9405       INTERP_KERNEL::NormalizedCellType typeOfSon;
9406       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9407       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9408       if(*it2>0)
9409         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9410       else
9411         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9412       if(edge1.size()==2)
9413         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9414       else
9415         {//the current edge has been subsplit -> create corresponding centers.
9416           std::size_t nbOfCentersToAppend(edge1.size()/2);
9417           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9418           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9419           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9420           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9421             {
9422               double tmpp[2];
9423               const double *aa(coordsPtr+2*(*it3++));
9424               const double *bb(coordsPtr+2*(*it3++));
9425               ee->getMiddleOfPoints(aa,bb,tmpp);
9426               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9427               centers.push_back(offset+k);
9428             }
9429         }
9430     }
9431   std::size_t nb(allEdges.size());
9432   if(nb%2!=0)
9433     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9434   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9435   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9436   if(addCoo->empty())
9437     ret->setCoords(coords);
9438   else
9439     {
9440       addCoo->rearrange(2);
9441       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9442       ret->setCoords(addCoo);
9443     }
9444   ret->allocateCells(1);
9445   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9446   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9447     connOut[kk]=allEdges[2*kk];
9448   connOut.insert(connOut.end(),centers.begin(),centers.end());
9449   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9450   return ret.retn();
9451 }
9452
9453 /*!
9454  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9455  * of those edges.
9456  *
9457  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9458  */
9459 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9460 {
9461   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9462   if(!cm.isQuadratic())
9463     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9464   else
9465     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9466 }
9467
9468 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edges)
9469 {
9470   bool isQuad(false);
9471   for(std::vector< MCAuto<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9472     {
9473       const INTERP_KERNEL::Edge *ee(*it);
9474       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9475         isQuad=true;
9476     }
9477   if(!isQuad)
9478     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9479   else
9480     {
9481       const double *coo(mesh2D->getCoords()->begin());
9482       std::size_t sz(conn.size());
9483       std::vector<double> addCoo;
9484       std::vector<int> conn2(conn);
9485       int offset(mesh2D->getNumberOfNodes());
9486       for(std::size_t i=0;i<sz;i++)
9487         {
9488           double tmp[2];
9489           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9490           addCoo.insert(addCoo.end(),tmp,tmp+2);
9491           conn2.push_back(offset+(int)i);
9492         }
9493       mesh2D->getCoords()->rearrange(1);
9494       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9495       mesh2D->getCoords()->rearrange(2);
9496       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9497     }
9498 }
9499
9500 /*!
9501  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9502  *
9503  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9504  * a set of edges defined in \a splitMesh1D.
9505  */
9506 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edge1BisPtr,
9507                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& out1)
9508 {
9509   std::size_t nb(edge1Bis.size()/2);
9510   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9511   int iEnd(splitMesh1D->getNumberOfCells());
9512   if(iEnd==0)
9513     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9514   std::size_t ii,jj;
9515   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9516   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9517   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9518   //
9519   if(jj==nb)
9520     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9521       out0.resize(1); out1.resize(1);
9522       std::vector<int>& connOut(out0[0]);
9523       connOut.resize(nbOfEdgesOf2DCellSplit);
9524       std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9525       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9526       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9527         {
9528           connOut[kk]=edge1Bis[2*kk];
9529           edgesPtr[kk]=edge1BisPtr[2*kk];
9530         }
9531     }
9532   else
9533     {
9534       // [i,iEnd[ contains the
9535       out0.resize(2); out1.resize(2);
9536       std::vector<int>& connOutLeft(out0[0]);
9537       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9538       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9539       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eright(out1[1]);
9540       for(std::size_t k=ii;k<jj+1;k++)
9541         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9542       std::vector< MCAuto<INTERP_KERNEL::Edge> > ees(iEnd);
9543       for(int ik=0;ik<iEnd;ik++)
9544         {
9545           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9546           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9547           ees[ik]=ee;
9548         }
9549       for(int ik=iEnd-1;ik>=0;ik--)
9550         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9551       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9552         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9553       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9554       for(int ik=0;ik<iEnd;ik++)
9555         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9556       eright.insert(eright.end(),ees.begin(),ees.end());
9557     }
9558 }
9559
9560 /// @endcond
9561
9562 /// @cond INTERNAL
9563
9564 struct CellInfo
9565 {
9566 public:
9567   CellInfo() { }
9568   CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9569 public:
9570   std::vector<int> _edges;
9571   std::vector< MCAuto<INTERP_KERNEL::Edge> > _edges_ptr;
9572 };
9573
9574 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr)
9575 {
9576   std::size_t nbe(edges.size());
9577   std::vector<int> edges2(2*nbe); std::vector< MCAuto<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9578   for(std::size_t i=0;i<nbe;i++)
9579     {
9580       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9581       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9582     }
9583   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9584   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9585   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9586 }
9587
9588 class EdgeInfo
9589 {
9590 public:
9591   EdgeInfo(int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9592   EdgeInfo(int istart, int iend, int pos, const MCAuto<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9593   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9594   void somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9595   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9596 private:
9597   int _istart;
9598   int _iend;
9599   MCAuto<MEDCouplingUMesh> _mesh;
9600   MCAuto<INTERP_KERNEL::Edge> _edge;
9601   int _left;
9602   int _right;
9603 };
9604
9605 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9606 {
9607   const MEDCouplingUMesh *mesh(_mesh);
9608   if(mesh)
9609     return ;
9610   if(_right<pos)
9611     return ;
9612   if(_left>pos)
9613     { _left++; _right++; return ; }
9614   if(_right==pos)
9615     {
9616       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9617       if((isLeft && isRight) || (!isLeft && !isRight))
9618         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9619       if(isLeft)
9620         return ;
9621       if(isRight)
9622         {
9623           _right++;
9624           return ;
9625         }
9626     }
9627   if(_left==pos)
9628     {
9629       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9630       if((isLeft && isRight) || (!isLeft && !isRight))
9631         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9632       if(isLeft)
9633         {
9634           _right++;
9635           return ;
9636         }
9637       if(isRight)
9638         {
9639           _left++;
9640           _right++;
9641           return ;
9642         }
9643     }
9644 }
9645
9646 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9647 {
9648   const MEDCouplingUMesh *mesh(_mesh);
9649   if(!mesh)
9650     {
9651       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9652     }
9653   else
9654     {// not fully splitting cell case
9655       if(mesh2D->getNumberOfCells()==1)
9656         {//little optimization. 1 cell no need to find in which cell mesh is !
9657           neighbors[0]=offset; neighbors[1]=offset;
9658           return;
9659         }
9660       else
9661         {
9662           MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9663           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9664           if(cellId==-1)
9665             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9666           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9667         }
9668     }
9669 }
9670
9671 class VectorOfCellInfo
9672 {
9673 public:
9674   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9675   std::size_t size() const { return _pool.size(); }
9676   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9677   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);
9678   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9679   const std::vector< MCAuto<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9680   MCAuto<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9681   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9682 private:
9683   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9684   void updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9685   const CellInfo& get(int pos) const;
9686   CellInfo& get(int pos);
9687 private:
9688   std::vector<CellInfo> _pool;
9689   MCAuto<MEDCouplingUMesh> _ze_mesh;
9690   std::vector<EdgeInfo> _edge_info;
9691 };
9692
9693 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9694 {
9695   _pool[0]._edges=edges;
9696   _pool[0]._edges_ptr=edgesPtr;
9697 }
9698
9699 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9700 {
9701   if(_pool.empty())
9702     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9703   if(_pool.size()==1)
9704     return 0;
9705   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9706   if(!zeMesh)
9707     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9708   MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9709   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9710 }
9711
9712 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)
9713 {
9714   get(pos);//to check pos
9715   bool isFast(pos==0 && _pool.size()==1);
9716   std::size_t sz(edges.size());
9717   // dealing with edges
9718   if(sz==1)
9719     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9720   else
9721     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9722   //
9723   std::vector<CellInfo> pool(_pool.size()-1+sz);
9724   for(int i=0;i<pos;i++)
9725     pool[i]=_pool[i];
9726   for(std::size_t j=0;j<sz;j++)
9727     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9728   for(int i=pos+1;i<(int)_pool.size();i++)
9729     pool[i+sz-1]=_pool[i];
9730   _pool=pool;
9731   //
9732   if(sz==2)
9733     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9734   //
9735   if(isFast)
9736     {
9737       _ze_mesh=mesh;
9738       return ;
9739     }
9740   //
9741   std::vector< MCAuto<MEDCouplingUMesh> > ms;
9742   if(pos>0)
9743     {
9744       MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(0,pos,true)));
9745       ms.push_back(elt);
9746     }
9747   ms.push_back(mesh);
9748   if(pos<_ze_mesh->getNumberOfCells()-1)
9749   {
9750     MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(pos+1,_ze_mesh->getNumberOfCells(),true)));
9751     ms.push_back(elt);
9752   }
9753   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9754   for(std::size_t j=0;j<ms2.size();j++)
9755     ms2[j]=ms[j];
9756   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9757 }
9758
9759 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9760 {
9761   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9762 }
9763
9764 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9765 {
9766   if(pos<0)
9767     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9768   int ret(0);
9769   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9770     {
9771       if((*it).isInMyRange(pos))
9772         return ret;
9773     }
9774   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9775 }
9776
9777 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9778 {
9779   get(pos);//to check;
9780   if(_edge_info.empty())
9781     return ;
9782   std::size_t sz(_edge_info.size()-1);
9783   for(std::size_t i=0;i<sz;i++)
9784     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9785 }
9786
9787 const CellInfo& VectorOfCellInfo::get(int pos) const
9788 {
9789   if(pos<0 || pos>=(int)_pool.size())
9790     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9791   return _pool[pos];
9792 }
9793
9794 CellInfo& VectorOfCellInfo::get(int pos)
9795 {
9796   if(pos<0 || pos>=(int)_pool.size())
9797     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9798   return _pool[pos];
9799 }
9800
9801 /*!
9802  * Given :
9803  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9804  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9805  *
9806  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9807  *
9808  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9809  *
9810  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9811  */
9812 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9813                                          MCAuto<DataArrayInt>& idsLeftRight)
9814 {
9815   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9816   if(nbCellsInSplitMesh1D==0)
9817     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9818   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9819   std::size_t nb(allEdges.size()),jj;
9820   if(nb%2!=0)
9821     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9822   std::vector<int> edge1Bis(nb*2);
9823   std::vector< MCAuto<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9824   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9825   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9826   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9827   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9828   //
9829   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9830   int *idsLeftRightPtr(idsLeftRight->getPointer());
9831   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9832   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9833     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9834       int iEnd(iStart);
9835       for(;iEnd<nbCellsInSplitMesh1D;)
9836         {
9837           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9838           if(jj!=nb)
9839             break;
9840           else
9841             iEnd++;
9842         }
9843       if(iEnd<nbCellsInSplitMesh1D)
9844         iEnd++;
9845       //
9846       MCAuto<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelfSlice(iStart,iEnd,1,true)));
9847       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9848       //
9849       MCAuto<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9850       retTmp->setCoords(splitMesh1D->getCoords());
9851       retTmp->allocateCells();
9852
9853       std::vector< std::vector<int> > out0;
9854       std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > > out1;
9855
9856       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9857       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9858         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9859       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9860       //
9861       iStart=iEnd;
9862     }
9863   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9864     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9865   return pool.getZeMesh().retn();
9866 }
9867
9868 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9869                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9870                                      MCAuto<DataArrayInt>& idsLeftRight)
9871 {
9872   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9873   //
9874   std::vector<int> allEdges;
9875   std::vector< MCAuto<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9876   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9877     {
9878       int edgeId(std::abs(*it)-1);
9879       std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9880       MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9881       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9882       if(*it>0)
9883         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9884       else
9885         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9886       std::size_t sz(edge1.size());
9887       for(std::size_t cnt=0;cnt<sz;cnt++)
9888         allEdgesPtr.push_back(ee);
9889     }
9890   //
9891   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9892 }
9893
9894 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9895 {
9896   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9897     {//easy case comparison not
9898       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9899     }
9900   else if(typ1.isQuadratic() && typ2.isQuadratic())
9901     {
9902       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9903       if(!status0)
9904         return false;
9905       if(conn1[2]==conn2[2])
9906         return true;
9907       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9908       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9909       return dist<eps;
9910     }
9911   else
9912     {//only one is quadratic
9913       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9914       if(!status0)
9915         return false;
9916       const double *a(0),*bb(0),*be(0);
9917       if(typ1.isQuadratic())
9918         {
9919           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9920         }
9921       else
9922         {
9923           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9924         }
9925       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9926       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9927       return dist<eps;
9928     }
9929 }
9930
9931 /*!
9932  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9933  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9934  *
9935  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9936  */
9937 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9938 {
9939   if(candidatesIn2DEnd==candidatesIn2DBg)
9940     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9941   const double *coo(mesh2DSplit->getCoords()->begin());
9942   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9943     return *candidatesIn2DBg;
9944   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9945   MCAuto<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9946   if(cellIdInMesh1DSplitRelative<0)
9947     cur1D->changeOrientationOfCells();
9948   const int *c1D(cur1D->getNodalConnectivity()->begin());
9949   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9950   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9951     {
9952       MCAuto<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9953       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9954       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9955       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9956       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9957       for(unsigned it2=0;it2<sz;it2++)
9958         {
9959           INTERP_KERNEL::NormalizedCellType typeOfSon;
9960           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9961           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9962           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9963             return *it;
9964         }
9965     }
9966   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9967 }
9968
9969 /// @endcond
9970
9971 /*!
9972  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9973  * 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
9974  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9975  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9976  *
9977  * \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
9978  *                      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)
9979  * \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
9980  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9981  * \param [in] eps - precision used to perform intersections and localization operations.
9982  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9983  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9984  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9985  *                               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.
9986  * \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
9987  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9988  *                               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.
9989  *
9990  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9991  */
9992 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9993 {
9994   if(!mesh2D || !mesh1D)
9995     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9996   mesh2D->checkFullyDefined();
9997   mesh1D->checkFullyDefined();
9998   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9999   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
10000     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
10001   // Step 1: compute all edge intersections (new nodes)
10002   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
10003   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
10004   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10005   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10006   //
10007   // Build desc connectivity
10008   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
10009   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10010   MCAuto<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
10011   std::map<int,int> mergedNodes;
10012   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
10013   // use mergeNodes to fix intersectEdge1
10014   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
10015     {
10016       std::size_t n((*it0).size()/2);
10017       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
10018       std::map<int,int>::const_iterator it1;
10019       it1=mergedNodes.find(eltStart);
10020       if(it1!=mergedNodes.end())
10021         (*it0)[0]=(*it1).second;
10022       it1=mergedNodes.find(eltEnd);
10023       if(it1!=mergedNodes.end())
10024         (*it0)[2*n-1]=(*it1).second;
10025     }
10026   //
10027   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
10028   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
10029   // Step 2: re-order newly created nodes according to the ordering found in m2
10030   std::vector< std::vector<int> > intersectEdge2;
10031   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
10032   subDiv2.clear();
10033   // Step 3: compute splitMesh1D
10034   MCAuto<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
10035   MCAuto<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
10036   MCAuto<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
10037       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
10038   MCAuto<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
10039   MCAuto<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
10040   // deal with cells in mesh2D that are not cut but only some of their edges are
10041   MCAuto<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCopy());
10042   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
10043   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
10044   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
10045   if(!idsInDesc2DToBeRefined->empty())
10046     {
10047       DataArrayInt *out0(0),*outi0(0);
10048       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
10049       MCAuto<DataArrayInt> outi0s(outi0);
10050       out0s=out0;
10051       out0s=out0s->buildUnique();
10052       out0s->sort(true);
10053     }
10054   //
10055   MCAuto<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
10056   MCAuto<DataArrayDouble> baryRet1(ret1NonCol->computeCellCenterOfMass());
10057   MCAuto<DataArrayInt> elts,eltsIndex;
10058   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
10059   MCAuto<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
10060   MCAuto<DataArrayInt> eltsIndex3(eltsIndex2->findIdsEqual(1));
10061   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
10062     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
10063   MCAuto<DataArrayInt> cellsToBeModified(elts->buildUnique());
10064   MCAuto<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
10065   if((DataArrayInt *)out0s)
10066     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
10067   std::vector< MCAuto<MEDCouplingUMesh> > outMesh2DSplit;
10068   // OK all is ready to insert in ret2 mesh
10069   if(!untouchedCells->empty())
10070     {// the most easy part, cells in mesh2D not impacted at all
10071       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
10072       outMesh2DSplit.back()->setCoords(ret1->getCoords());
10073       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
10074     }
10075   if((DataArrayInt *)out0s)
10076     {// here dealing with cells in out0s but not in cellsToBeModified
10077       MCAuto<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
10078       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
10079       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
10080         {
10081           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
10082           ret1->setCoords(outMesh2DSplit.back()->getCoords());
10083         }
10084       int offset(ret2->getNumberOfTuples());
10085       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
10086       MCAuto<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
10087       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
10088       int kk(0),*ret3ptr(partOfRet3->getPointer());
10089       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
10090         {
10091           int faceId(std::abs(*it)-1);
10092           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
10093             {
10094               int tmp(fewModifiedCells->findIdFirstEqual(*it2));
10095               if(tmp!=-1)
10096                 {
10097                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
10098                     ret3ptr[2*kk]=tmp+offset;
10099                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
10100                     ret3ptr[2*kk+1]=tmp+offset;
10101                 }
10102               else
10103                 {//the current edge is shared by a 2D cell that will be split just after
10104                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
10105                     ret3ptr[2*kk]=-(*it2+1);
10106                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
10107                     ret3ptr[2*kk+1]=-(*it2+1);
10108                 }
10109             }
10110         }
10111       m1Desc->setCoords(ret1->getCoords());
10112       ret1NonCol->setCoords(ret1->getCoords());
10113       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
10114       if(!outMesh2DSplit.empty())
10115         {
10116           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
10117           for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
10118             (*itt)->setCoords(da);
10119         }
10120     }
10121   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
10122   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
10123     {
10124       MCAuto<DataArrayInt> idsNonColPerCell(elts->findIdsEqual(*it));
10125       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
10126       MCAuto<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
10127       MCAuto<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
10128       MCAuto<DataArrayInt> partOfRet3;
10129       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));
10130       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
10131       outMesh2DSplit.push_back(splitOfOneCell);
10132       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
10133         ret2->pushBackSilent(*it);
10134     }
10135   //
10136   std::size_t nbOfMeshes(outMesh2DSplit.size());
10137   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
10138   for(std::size_t i=0;i<nbOfMeshes;i++)
10139     tmp[i]=outMesh2DSplit[i];
10140   //
10141   ret1->getCoords()->setInfoOnComponents(compNames);
10142   MCAuto<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
10143   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
10144   ret3->rearrange(1);
10145   MCAuto<DataArrayInt> edgesToDealWith(ret3->findIdsStricltyNegative());
10146   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
10147     {
10148       int old2DCellId(-ret3->getIJ(*it,0)-1);
10149       MCAuto<DataArrayInt> candidates(ret2->findIdsEqual(old2DCellId));
10150       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
10151     }
10152   ret3->changeValue(std::numeric_limits<int>::max(),-1);
10153   ret3->rearrange(2);
10154   //
10155   splitMesh1D=ret1.retn();
10156   splitMesh2D=ret2D.retn();
10157   cellIdInMesh2D=ret2.retn();
10158   cellIdInMesh1D=ret3.retn();
10159 }
10160
10161 /**
10162  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
10163  * (newly created) nodes corresponding to the edge intersections.
10164  * Output params:
10165  * @param[out] cr, crI connectivity of the resulting mesh
10166  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
10167  * TODO: describe input parameters
10168  */
10169 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
10170                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
10171                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
10172                                                          const std::vector<double>& addCoords,
10173                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
10174 {
10175   static const int SPACEDIM=2;
10176   const double *coo1(m1->getCoords()->getConstPointer());
10177   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
10178   int offset1(m1->getNumberOfNodes());
10179   const double *coo2(m2->getCoords()->getConstPointer());
10180   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
10181   int offset2(offset1+m2->getNumberOfNodes());
10182   int offset3(offset2+((int)addCoords.size())/2);
10183   MCAuto<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
10184   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10185   // Here a BBTree on 2D-cells, not on segments:
10186   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
10187   int ncell1(m1->getNumberOfCells());
10188   crI.push_back(0);
10189   for(int i=0;i<ncell1;i++)
10190     {
10191       std::vector<int> candidates2;
10192       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10193       std::map<INTERP_KERNEL::Node *,int> mapp;
10194       std::map<int,INTERP_KERNEL::Node *> mappRev;
10195       INTERP_KERNEL::QuadraticPolygon pol1;
10196       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
10197       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
10198       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
10199       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
10200       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
10201       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
10202           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
10203       //
10204       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
10205       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
10206       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10207       for(it1.first();!it1.finished();it1.next())
10208         edges1.insert(it1.current()->getPtr());
10209       //
10210       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10211       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10212       int ii=0;
10213       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10214         {
10215           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10216           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10217           // Complete mapping with elements coming from the current cell it2 in mesh2:
10218           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10219           // pol2 is the new QP in the final merged result.
10220           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10221               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10222         }
10223       ii=0;
10224       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10225         {
10226           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10227           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10228           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10229           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10230         }
10231       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10232       // by m2 but that we still want to keep in the final result.
10233       if(!edges1.empty())
10234         {
10235           try
10236           {
10237               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10238           }
10239           catch(INTERP_KERNEL::Exception& e)
10240           {
10241               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();
10242               throw INTERP_KERNEL::Exception(oss.str());
10243           }
10244         }
10245       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10246         (*it).second->decrRef();
10247     }
10248 }
10249
10250 /**
10251  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10252  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10253  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10254  * The caller is to deal with the resulting DataArrayInt.
10255  *  \throw If the coordinate array is not set.
10256  *  \throw If the nodal connectivity of the cells is not defined.
10257  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10258  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10259  *
10260  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10261  */
10262 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10263 {
10264   checkFullyDefined();
10265   if(getMeshDimension()!=1)
10266     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10267
10268   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10269   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10270   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10271   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10272   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10273   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10274   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10275   const int * dsi(_dsi->getConstPointer());
10276   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
10277   m_points=0;
10278   if (dsii->getNumberOfTuples())
10279     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10280
10281   int nc(getNumberOfCells());
10282   MCAuto<DataArrayInt> result(DataArrayInt::New());
10283   result->alloc(nc,1);
10284
10285   // set of edges not used so far
10286   std::set<int> edgeSet;
10287   for (int i=0; i<nc; edgeSet.insert(i), i++);
10288
10289   int startSeg=0;
10290   int newIdx=0;
10291   // while we have points with only one neighbor segments
10292   do
10293     {
10294       std::list<int> linePiece;
10295       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10296       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10297         {
10298           // Fill the list forward (resp. backward) from the start segment:
10299           int activeSeg = startSeg;
10300           int prevPointId = -20;
10301           int ptId;
10302           while (!edgeSet.empty())
10303             {
10304               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10305                 {
10306                   if (direction==0)
10307                     linePiece.push_back(activeSeg);
10308                   else
10309                     linePiece.push_front(activeSeg);
10310                   edgeSet.erase(activeSeg);
10311                 }
10312
10313               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10314               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10315               if (dsi[ptId] == 1) // hitting the end of the line
10316                 break;
10317               prevPointId = ptId;
10318               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10319               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10320             }
10321         }
10322       // Done, save final piece into DA:
10323       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10324       newIdx += linePiece.size();
10325
10326       // identify next valid start segment (one which is not consumed)
10327       if(!edgeSet.empty())
10328         startSeg = *(edgeSet.begin());
10329     }
10330   while (!edgeSet.empty());
10331   return result.retn();
10332 }
10333
10334 /// @cond INTERNAL
10335
10336 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10337 {
10338   MCAuto<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10339   std::map<MCAuto<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10340   if(it==m.end())
10341     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10342   int v((*it).second);
10343   if(v==forbVal0 || v==forbVal1)
10344     return ;
10345   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10346     isect.push_back(v);
10347 }
10348
10349 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10350 {
10351   int sz(c.size());
10352   if(sz<=1)
10353     return false;
10354   bool presenceOfOn(false);
10355   for(int i=0;i<sz;i++)
10356     {
10357       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10358       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10359         continue ;
10360       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10361       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10362     }
10363   return presenceOfOn;
10364 }
10365
10366 /// @endcond
10367
10368 /**
10369  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10370  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10371  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10372  * a minimal creation of new nodes is wanted.
10373  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10374  * nodes if a SEG3 is split without information of middle.
10375  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10376  * avoid to have a non conform mesh.
10377  *
10378  * \return int - the number of new nodes created (in most of cases 0).
10379  * 
10380  * \throw If \a this is not coherent.
10381  * \throw If \a this has not spaceDim equal to 2.
10382  * \throw If \a this has not meshDim equal to 2.
10383  * \throw If some subcells needed to be split are orphan.
10384  * \sa MEDCouplingUMesh::conformize2D
10385  */
10386 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10387 {
10388   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10389     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10390   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10391   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10392     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10393   if(midOpt==0 && midOptI==0)
10394     {
10395       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10396       return 0;
10397     }
10398   else if(midOpt!=0 && midOptI!=0)
10399     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10400   else
10401     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10402 }
10403
10404 /*!
10405  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10406  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10407  * 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
10408  * 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).
10409  * 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.
10410  * 
10411  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10412  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10413  *
10414  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10415  * This method expects that all nodes in \a this are not closer than \a eps.
10416  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10417  * 
10418  * \param [in] eps the relative error to detect merged edges.
10419  * \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
10420  *                           that the user is expected to deal with.
10421  *
10422  * \throw If \a this is not coherent.
10423  * \throw If \a this has not spaceDim equal to 2.
10424  * \throw If \a this has not meshDim equal to 2.
10425  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10426  */
10427 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10428 {
10429   static const int SPACEDIM=2;
10430   checkConsistencyLight();
10431   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10432     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10433   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10434   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10435   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10436   MCAuto<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10437   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10438   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10439   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10440   std::vector<double> addCoo;
10441   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10442   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10443   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10444   for(int i=0;i<nDescCell;i++)
10445     {
10446       std::vector<int> candidates;
10447       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10448       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10449         if(*it>i)
10450           {
10451             std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10452             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10453                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10454             INTERP_KERNEL::MergePoints merge;
10455             INTERP_KERNEL::QuadraticPolygon c1,c2;
10456             e1->intersectWith(e2,merge,c1,c2);
10457             e1->decrRef(); e2->decrRef();
10458             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10459               overlapEdge[i].push_back(*it);
10460             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10461               overlapEdge[*it].push_back(i);
10462           }
10463     }
10464   // splitting done. sort intersect point in intersectEdge.
10465   std::vector< std::vector<int> > middle(nDescCell);
10466   int nbOf2DCellsToBeSplit(0);
10467   bool middleNeedsToBeUsed(false);
10468   std::vector<bool> cells2DToTreat(nDescCell,false);
10469   for(int i=0;i<nDescCell;i++)
10470     {
10471       std::vector<int>& isect(intersectEdge[i]);
10472       int sz((int)isect.size());
10473       if(sz>1)
10474         {
10475           std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10476           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10477           e->sortSubNodesAbs(coords,isect);
10478           e->decrRef();
10479         }
10480       if(sz!=0)
10481         {
10482           int idx0(rdi[i]),idx1(rdi[i+1]);
10483           if(idx1-idx0!=1)
10484             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10485           if(!cells2DToTreat[rd[idx0]])
10486             {
10487               cells2DToTreat[rd[idx0]]=true;
10488               nbOf2DCellsToBeSplit++;
10489             }
10490           // try to reuse at most eventual 'middle' of SEG3
10491           std::vector<int>& mid(middle[i]);
10492           mid.resize(sz+1,-1);
10493           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10494             {
10495               middleNeedsToBeUsed=true;
10496               const std::vector<int>& candidates(overlapEdge[i]);
10497               std::vector<int> trueCandidates;
10498               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10499                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10500                   trueCandidates.push_back(*itc);
10501               int stNode(c[ci[i]+1]),endNode(isect[0]);
10502               for(int j=0;j<sz+1;j++)
10503                 {
10504                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10505                     {
10506                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10507                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10508                         { mid[j]=*itc; break; }
10509                     }
10510                   stNode=endNode;
10511                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10512                 }
10513             }
10514         }
10515     }
10516   MCAuto<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10517   if(nbOf2DCellsToBeSplit==0)
10518     return ret.retn();
10519   //
10520   int *retPtr(ret->getPointer());
10521   for(int i=0;i<nCell;i++)
10522     if(cells2DToTreat[i])
10523       *retPtr++=i;
10524   //
10525   MCAuto<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10526   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10527   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10528   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10529   if(middleNeedsToBeUsed)
10530     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10531   MCAuto<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10532   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10533   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.
10534   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10535   {
10536     bool areNodesMerged; int newNbOfNodes;
10537     if(nbOfNodesCreated!=0)
10538       MCAuto<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10539   }
10540   return ret.retn();
10541 }
10542
10543 /*!
10544  * 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.
10545  * 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).
10546  * 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
10547  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10548  * 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
10549  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10550  *
10551  * 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
10552  * using new instance, idem for coordinates.
10553  *
10554  * 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.
10555  * 
10556  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10557  *
10558  * \throw If \a this is not coherent.
10559  * \throw If \a this has not spaceDim equal to 2.
10560  * \throw If \a this has not meshDim equal to 2.
10561  * 
10562  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10563  */
10564 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10565 {
10566   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10567   checkConsistencyLight();
10568   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10569     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10570   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10571   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10572   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10573   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10574   MCAuto<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10575   MCAuto<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10576   const double *coords(_coords->begin());
10577   int *newciptr(newci->getPointer());
10578   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10579     {
10580       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10581         ret->pushBackSilent(i);
10582       newciptr[1]=newc->getNumberOfTuples();
10583     }
10584   //
10585   if(ret->empty())
10586     return ret.retn();
10587   if(!appendedCoords->empty())
10588     {
10589       appendedCoords->rearrange(2);
10590       MCAuto<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10591       //non const part
10592       setCoords(newCoords);
10593     }
10594   //non const part
10595   setConnectivity(newc,newci,true);
10596   return ret.retn();
10597 }
10598
10599 /*!
10600  * \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.
10601  *                               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.
10602  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10603  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10604  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10605  * \param [out] addCoo - nodes to be append at the end
10606  * \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.
10607  */
10608 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10609                                          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)
10610 {
10611   static const int SPACEDIM=2;
10612   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10613   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10614   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10615   // Build BB tree of all edges in the tool mesh (second mesh)
10616   MCAuto<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10617   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10618   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10619   intersectEdge1.resize(nDescCell1);
10620   colinear2.resize(nDescCell2);
10621   subDiv2.resize(nDescCell2);
10622   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10623
10624   std::vector<int> candidates1(1);
10625   int offset1(m1Desc->getNumberOfNodes());
10626   int offset2(offset1+m2Desc->getNumberOfNodes());
10627   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10628     {
10629       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10630       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10631       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10632         {
10633           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10634           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10635           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10636           candidates1[0]=i;
10637           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10638           // 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
10639           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10640           std::set<INTERP_KERNEL::Node *> nodes;
10641           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10642           std::size_t szz(nodes.size());
10643           std::vector< MCAuto<INTERP_KERNEL::Node> > nodesSafe(szz);
10644           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10645           for(std::size_t iii=0;iii<szz;iii++,itt++)
10646             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10647           // end of protection
10648           // Performs egde cutting:
10649           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10650           delete pol2;
10651           delete pol1;
10652         }
10653       else
10654         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10655         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10656     }
10657 }
10658
10659 /*!
10660  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10661  * It builds the descending connectivity of the two meshes, and then using a binary tree
10662  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10663  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10664  */
10665 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10666                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10667                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10668                                                    std::vector<double>& addCoo,
10669                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10670 {
10671   // Build desc connectivity
10672   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10673   desc2=DataArrayInt::New();
10674   descIndx2=DataArrayInt::New();
10675   revDesc2=DataArrayInt::New();
10676   revDescIndx2=DataArrayInt::New();
10677   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10678   MCAuto<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10679   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10680   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10681   MCAuto<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10682   std::map<int,int> notUsedMap;
10683   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10684   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10685   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10686 }
10687
10688 /*!
10689  * This method performs the 2nd step of Partition of 2D mesh.
10690  * This method has 4 inputs :
10691  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10692  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10693  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10694  * 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'
10695  * Nodes end up lying consecutively on a cutted edge.
10696  * \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.
10697  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10698  * \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.
10699  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10700  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10701  */
10702 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10703                                            const std::vector<double>& addCoo,
10704                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10705 {
10706   int offset1=m1->getNumberOfNodes();
10707   int ncell=m2->getNumberOfCells();
10708   const int *c=m2->getNodalConnectivity()->getConstPointer();
10709   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10710   const double *coo=m2->getCoords()->getConstPointer();
10711   const double *cooBis=m1->getCoords()->getConstPointer();
10712   int offset2=offset1+m2->getNumberOfNodes();
10713   intersectEdge.resize(ncell);
10714   for(int i=0;i<ncell;i++,cI++)
10715     {
10716       const std::vector<int>& divs=subDiv[i];
10717       int nnode=cI[1]-cI[0]-1;
10718       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10719       std::map<INTERP_KERNEL::Node *, int> mapp22;
10720       for(int j=0;j<nnode;j++)
10721         {
10722           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10723           int nnid=c[(*cI)+j+1];
10724           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10725           mapp22[nn]=nnid+offset1;
10726         }
10727       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10728       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10729         ((*it).second.first)->decrRef();
10730       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10731       std::map<INTERP_KERNEL::Node *,int> mapp3;
10732       for(std::size_t j=0;j<divs.size();j++)
10733         {
10734           int id=divs[j];
10735           INTERP_KERNEL::Node *tmp=0;
10736           if(id<offset1)
10737             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10738           else if(id<offset2)
10739             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10740           else
10741             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10742           addNodes[j]=tmp;
10743           mapp3[tmp]=id;
10744         }
10745       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10746       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10747         (*it)->decrRef();
10748       e->decrRef();
10749     }
10750 }
10751
10752 /*!
10753  * 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).
10754  * 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
10755  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10756  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10757  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10758  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10759  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10760  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10761  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10762  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10763  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10764  * \param [out] cut3DSuf input/output param.
10765  */
10766 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10767                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10768                                                    const int *desc, const int *descIndx, 
10769                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10770 {
10771   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10772   int nbOf3DSurfCell=(int)cut3DSurf.size();
10773   for(int i=0;i<nbOf3DSurfCell;i++)
10774     {
10775       std::vector<int> res;
10776       int offset=descIndx[i];
10777       int nbOfSeg=descIndx[i+1]-offset;
10778       for(int j=0;j<nbOfSeg;j++)
10779         {
10780           int edgeId=desc[offset+j];
10781           int status=cut3DCurve[edgeId];
10782           if(status!=-2)
10783             {
10784               if(status>-1)
10785                 res.push_back(status);
10786               else
10787                 {
10788                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10789                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10790                 }
10791             }
10792         }
10793       switch(res.size())
10794       {
10795         case 2:
10796           {
10797             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10798             break;
10799           }
10800         case 1:
10801         case 0:
10802           {
10803             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10804             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10805             if(res.size()==2)
10806               {
10807                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10808               }
10809             else
10810               {
10811                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10812               }
10813             break;
10814           }
10815         default:
10816           {// case when plane is on a multi colinear edge of a polyhedron
10817             if((int)res.size()==2*nbOfSeg)
10818               {
10819                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10820               }
10821             else
10822               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10823           }
10824       }
10825     }
10826 }
10827
10828 /*!
10829  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10830  * 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).
10831  * 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
10832  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10833  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10834  * \param desc is the descending connectivity 3D->3DSurf
10835  * \param descIndx is the descending connectivity index 3D->3DSurf
10836  */
10837 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10838                                                   const int *desc, const int *descIndx,
10839                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10840 {
10841   checkFullyDefined();
10842   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10843     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10844   const int *nodal3D(_nodal_connec->begin()),*nodalIndx3D(_nodal_connec_index->begin());
10845   int nbOfCells(getNumberOfCells());
10846   for(int i=0;i<nbOfCells;i++)
10847     {
10848       std::map<int, std::set<int> > m;
10849       int offset=descIndx[i];
10850       int nbOfFaces=descIndx[i+1]-offset;
10851       int start=-1;
10852       int end=-1;
10853       for(int j=0;j<nbOfFaces;j++)
10854         {
10855           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10856           if(p.first!=-1 && p.second!=-1)
10857             {
10858               if(p.first!=-2)
10859                 {
10860                   start=p.first; end=p.second;
10861                   m[p.first].insert(p.second);
10862                   m[p.second].insert(p.first);
10863                 }
10864               else
10865                 {
10866                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10867                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10868                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10869                   INTERP_KERNEL::NormalizedCellType cmsId;
10870                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10871                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10872                   for(unsigned k=0;k<nbOfNodesSon;k++)
10873                     {
10874                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10875                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10876                     }
10877                 }
10878             }
10879         }
10880       if(m.empty())
10881         continue;
10882       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10883       int prev=end;
10884       while(end!=start)
10885         {
10886           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10887           const std::set<int>& s=(*it).second;
10888           std::set<int> s2; s2.insert(prev);
10889           std::set<int> s3;
10890           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10891           if(s3.size()==1)
10892             {
10893               int val=*s3.begin();
10894               conn.push_back(start);
10895               prev=start;
10896               start=val;
10897             }
10898           else
10899             start=end;
10900         }
10901       conn.push_back(end);
10902       if(conn.size()>3)
10903         {
10904           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10905           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10906           cellIds->pushBackSilent(i);
10907         }
10908     }
10909 }
10910
10911 void InsertNodeInConnIfNecessary(int nodeIdToInsert, std::vector<int>& conn, const double *coords, double eps)
10912 {
10913   std::vector<int>::iterator it(std::find(conn.begin(),conn.end(),nodeIdToInsert));
10914   if(it!=conn.end())
10915     return ;
10916   std::size_t sz(conn.size());
10917   std::size_t found(std::numeric_limits<std::size_t>::max());
10918   for(std::size_t i=0;i<sz;i++)
10919     {
10920       int pt0(conn[i]),pt1(conn[(i+1)%sz]);
10921       double v1[3]={coords[3*pt1+0]-coords[3*pt0+0],coords[3*pt1+1]-coords[3*pt0+1],coords[3*pt1+2]-coords[3*pt0+2]},v2[3]={coords[3*nodeIdToInsert+0]-coords[3*pt0+0],coords[3*nodeIdToInsert+1]-coords[3*pt0+1],coords[3*nodeIdToInsert+2]-coords[3*pt0+2]};
10922       double normm(sqrt(v1[0]*v1[0]+v1[1]*v1[1]+v1[2]*v1[2]));
10923       std::transform(v1,v1+3,v1,std::bind2nd(std::multiplies<double>(),1./normm));
10924       std::transform(v2,v2+3,v2,std::bind2nd(std::multiplies<double>(),1./normm));
10925       double v3[3];
10926       v3[0]=v1[1]*v2[2]-v1[2]*v2[1]; v3[1]=v1[2]*v2[0]-v1[0]*v2[2]; v3[2]=v1[0]*v2[1]-v1[1]*v2[0];
10927       double normm2(sqrt(v3[0]*v3[0]+v3[1]*v3[1]+v3[2]*v3[2])),dotTest(v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]);
10928       if(normm2<eps)
10929         if(dotTest>eps && dotTest<1.-eps)
10930           {
10931             found=i;
10932             break;
10933           }
10934     }
10935   if(found==std::numeric_limits<std::size_t>::max())
10936     throw INTERP_KERNEL::Exception("InsertNodeInConnIfNecessary : not found point !");
10937   conn.insert(conn.begin()+(found+1)%sz,nodeIdToInsert);
10938 }
10939
10940 void SplitIntoToPart(const std::vector<int>& conn, int pt0, int pt1, std::vector<int>& part0, std::vector<int>& part1)
10941 {
10942   std::size_t sz(conn.size());
10943   std::vector<int> *curPart(&part0);
10944   for(std::size_t i=0;i<sz;i++)
10945     {
10946       int nextt(conn[(i+1)%sz]);
10947       (*curPart).push_back(nextt);
10948       if(nextt==pt0 || nextt==pt1)
10949         {
10950           if(curPart==&part0)
10951             curPart=&part1;
10952           else
10953             curPart=&part0;
10954           (*curPart).push_back(nextt);
10955         }
10956     }
10957 }
10958
10959 /*!
10960  * this method method splits cur cells 3D Surf in sub cells 3DSurf using the previous subsplit. This method is the last one used to clip.
10961  */
10962 void MEDCouplingUMesh::buildSubCellsFromCut(const std::vector< std::pair<int,int> >& cut3DSurf,
10963                                             const int *desc, const int *descIndx, const double *coords, double eps,
10964                                             std::vector<std::vector<int> >& res) const
10965 {
10966   checkFullyDefined();
10967   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10968     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSubCellsFromCut works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10969   const int *nodal3D(_nodal_connec->begin()),*nodalIndx3D(_nodal_connec_index->begin());
10970   int nbOfCells(getNumberOfCells());
10971   if(nbOfCells!=1)
10972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSubCellsFromCut works only with single cell presently !");
10973   for(int i=0;i<nbOfCells;i++)
10974     {
10975       int offset(descIndx[i]),nbOfFaces(descIndx[i+1]-offset),start(-1),end(-1);
10976       for(int j=0;j<nbOfFaces;j++)
10977         {
10978           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10979           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]));
10980           int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10981           INTERP_KERNEL::AutoPtr<int> tmp(new int[sz]);
10982           INTERP_KERNEL::NormalizedCellType cmsId;
10983           unsigned nbOfNodesSon(cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId));
10984           std::vector<int> elt((int *)tmp,(int *)tmp+nbOfNodesSon);
10985           if(p.first!=-1 && p.second!=-1)
10986             {
10987               if(p.first!=-2)
10988                 {
10989                   InsertNodeInConnIfNecessary(p.first,elt,coords,eps);
10990                   InsertNodeInConnIfNecessary(p.second,elt,coords,eps);
10991                   std::vector<int> elt1,elt2;
10992                   SplitIntoToPart(elt,p.first,p.second,elt1,elt2);
10993                   res.push_back(elt1);
10994                   res.push_back(elt2);
10995                 }
10996               else
10997                 res.push_back(elt);
10998             }
10999           else
11000             res.push_back(elt);
11001         }
11002     }
11003 }
11004
11005 /*!
11006  * 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
11007  * 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
11008  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
11009  * 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
11010  * 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.
11011  * 
11012  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
11013  */
11014 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
11015 {
11016   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
11017   if(sz>=4)
11018     {
11019       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
11020       if(cm.getDimension()==2)
11021         {
11022           const int *node=nodalConnBg+1;
11023           int startNode=*node++;
11024           double refX=coords[2*startNode];
11025           for(;node!=nodalConnEnd;node++)
11026             {
11027               if(coords[2*(*node)]<refX)
11028                 {
11029                   startNode=*node;
11030                   refX=coords[2*startNode];
11031                 }
11032             }
11033           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
11034           refX=1e300;
11035           double tmp1;
11036           double tmp2[2];
11037           double angle0=-M_PI/2;
11038           //
11039           int nextNode=-1;
11040           int prevNode=-1;
11041           double resRef;
11042           double angleNext=0.;
11043           while(nextNode!=startNode)
11044             {
11045               nextNode=-1;
11046               resRef=1e300;
11047               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
11048                 {
11049                   if(*node!=tmpOut.back() && *node!=prevNode)
11050                     {
11051                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
11052                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
11053                       double res;
11054                       if(angleM<=angle0)
11055                         res=angle0-angleM;
11056                       else
11057                         res=angle0-angleM+2.*M_PI;
11058                       if(res<resRef)
11059                         {
11060                           nextNode=*node;
11061                           resRef=res;
11062                           angleNext=angleM;
11063                         }
11064                     }
11065                 }
11066               if(nextNode!=startNode)
11067                 {
11068                   angle0=angleNext-M_PI;
11069                   if(angle0<-M_PI)
11070                     angle0+=2*M_PI;
11071                   prevNode=tmpOut.back();
11072                   tmpOut.push_back(nextNode);
11073                 }
11074             }
11075           std::vector<int> tmp3(2*(sz-1));
11076           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
11077           std::copy(nodalConnBg+1,nodalConnEnd,it);
11078           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
11079             {
11080               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
11081               return false;
11082             }
11083           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
11084             {
11085               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
11086               return false;
11087             }
11088           else
11089             {
11090               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
11091               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
11092               return true;
11093             }
11094         }
11095       else
11096         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
11097     }
11098   else
11099     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
11100 }
11101
11102 /*!
11103  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
11104  * 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.
11105  * 
11106  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
11107  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
11108  * \param [in,out] arr array in which the remove operation will be done.
11109  * \param [in,out] arrIndx array in the remove operation will modify
11110  * \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])
11111  * \return true if \b arr and \b arrIndx have been modified, false if not.
11112  */
11113 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
11114 {
11115   if(!arrIndx || !arr)
11116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
11117   if(offsetForRemoval<0)
11118     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
11119   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
11120   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
11121   int *arrIPtr=arrIndx->getPointer();
11122   *arrIPtr++=0;
11123   int previousArrI=0;
11124   const int *arrPtr=arr->getConstPointer();
11125   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
11126   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
11127     {
11128       if(*arrIPtr-previousArrI>offsetForRemoval)
11129         {
11130           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
11131             {
11132               if(s.find(*work)==s.end())
11133                 arrOut.push_back(*work);
11134             }
11135         }
11136       previousArrI=*arrIPtr;
11137       *arrIPtr=(int)arrOut.size();
11138     }
11139   if(arr->getNumberOfTuples()==(int)arrOut.size())
11140     return false;
11141   arr->alloc((int)arrOut.size(),1);
11142   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
11143   return true;
11144 }
11145
11146 /*!
11147  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
11148  * (\ref numbering-indirect).
11149  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
11150  * The selection of extraction is done standardly in new2old format.
11151  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
11152  *
11153  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11154  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11155  * \param [in] arrIn arr origin array from which the extraction will be done.
11156  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11157  * \param [out] arrOut the resulting array
11158  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11159  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
11160  */
11161 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11162                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11163 {
11164   if(!arrIn || !arrIndxIn)
11165     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
11166   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
11167   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
11168     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
11169   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
11170   const int *arrInPtr=arrIn->getConstPointer();
11171   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11172   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
11173   if(nbOfGrps<0)
11174     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
11175   int maxSizeOfArr=arrIn->getNumberOfTuples();
11176   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11177   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11178   arrIo->alloc((int)(sz+1),1);
11179   const int *idsIt=idsOfSelectBg;
11180   int *work=arrIo->getPointer();
11181   *work++=0;
11182   int lgth=0;
11183   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
11184     {
11185       if(*idsIt>=0 && *idsIt<nbOfGrps)
11186         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
11187       else
11188         {
11189           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
11190           throw INTERP_KERNEL::Exception(oss.str());
11191         }
11192       if(lgth>=work[-1])
11193         *work=lgth;
11194       else
11195         {
11196           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
11197           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
11198           throw INTERP_KERNEL::Exception(oss.str());
11199         }
11200     }
11201   arro->alloc(lgth,1);
11202   work=arro->getPointer();
11203   idsIt=idsOfSelectBg;
11204   for(std::size_t i=0;i<sz;i++,idsIt++)
11205     {
11206       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
11207         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
11208       else
11209         {
11210           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
11211           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11212           throw INTERP_KERNEL::Exception(oss.str());
11213         }
11214     }
11215   arrOut=arro.retn();
11216   arrIndexOut=arrIo.retn();
11217 }
11218
11219 /*!
11220  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
11221  * (\ref numbering-indirect).
11222  * 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 ).
11223  * The selection of extraction is done standardly in new2old format.
11224  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
11225  *
11226  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
11227  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
11228  * \param [in] idsOfSelectStep
11229  * \param [in] arrIn arr origin array from which the extraction will be done.
11230  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11231  * \param [out] arrOut the resulting array
11232  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11233  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
11234  */
11235 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11236                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11237 {
11238   if(!arrIn || !arrIndxIn)
11239     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
11240   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
11241   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
11242     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
11243   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
11244   const int *arrInPtr=arrIn->getConstPointer();
11245   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11246   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
11247   if(nbOfGrps<0)
11248     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
11249   int maxSizeOfArr=arrIn->getNumberOfTuples();
11250   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11251   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11252   arrIo->alloc((int)(sz+1),1);
11253   int idsIt=idsOfSelectStart;
11254   int *work=arrIo->getPointer();
11255   *work++=0;
11256   int lgth=0;
11257   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
11258     {
11259       if(idsIt>=0 && idsIt<nbOfGrps)
11260         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
11261       else
11262         {
11263           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
11264           throw INTERP_KERNEL::Exception(oss.str());
11265         }
11266       if(lgth>=work[-1])
11267         *work=lgth;
11268       else
11269         {
11270           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
11271           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
11272           throw INTERP_KERNEL::Exception(oss.str());
11273         }
11274     }
11275   arro->alloc(lgth,1);
11276   work=arro->getPointer();
11277   idsIt=idsOfSelectStart;
11278   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
11279     {
11280       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
11281         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
11282       else
11283         {
11284           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
11285           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11286           throw INTERP_KERNEL::Exception(oss.str());
11287         }
11288     }
11289   arrOut=arro.retn();
11290   arrIndexOut=arrIo.retn();
11291 }
11292
11293 /*!
11294  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11295  * 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
11296  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11297  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11298  *
11299  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11300  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11301  * \param [in] arrIn arr origin array from which the extraction will be done.
11302  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11303  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11304  * \param [in] srcArrIndex index array of \b srcArr
11305  * \param [out] arrOut the resulting array
11306  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11307  * 
11308  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11309  */
11310 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11311                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11312                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11313 {
11314   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11315     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11316   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11317   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11318   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11319   std::vector<bool> v(nbOfTuples,true);
11320   int offset=0;
11321   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11322   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11323   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11324     {
11325       if(*it>=0 && *it<nbOfTuples)
11326         {
11327           v[*it]=false;
11328           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11329         }
11330       else
11331         {
11332           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11333           throw INTERP_KERNEL::Exception(oss.str());
11334         }
11335     }
11336   srcArrIndexPtr=srcArrIndex->getConstPointer();
11337   arrIo->alloc(nbOfTuples+1,1);
11338   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11339   const int *arrInPtr=arrIn->getConstPointer();
11340   const int *srcArrPtr=srcArr->getConstPointer();
11341   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11342   int *arroPtr=arro->getPointer();
11343   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11344     {
11345       if(v[ii])
11346         {
11347           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11348           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11349         }
11350       else
11351         {
11352           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11353           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11354           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11355         }
11356     }
11357   arrOut=arro.retn();
11358   arrIndexOut=arrIo.retn();
11359 }
11360
11361 /*!
11362  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11363  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11364  *
11365  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11366  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11367  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11368  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11369  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11370  * \param [in] srcArrIndex index array of \b srcArr
11371  * 
11372  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11373  */
11374 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11375                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11376 {
11377   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11378     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11379   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11380   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11381   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11382   int *arrInOutPtr=arrInOut->getPointer();
11383   const int *srcArrPtr=srcArr->getConstPointer();
11384   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11385     {
11386       if(*it>=0 && *it<nbOfTuples)
11387         {
11388           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11389             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11390           else
11391             {
11392               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] !";
11393               throw INTERP_KERNEL::Exception(oss.str());
11394             }
11395         }
11396       else
11397         {
11398           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11399           throw INTERP_KERNEL::Exception(oss.str());
11400         }
11401     }
11402 }
11403
11404 /*!
11405  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11406  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11407  * 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]].
11408  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11409  * A negative value in \b arrIn means that it is ignored.
11410  * 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.
11411  * 
11412  * \param [in] arrIn arr origin array from which the extraction will be done.
11413  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11414  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11415  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11416  */
11417 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11418 {
11419   int seed=0,nbOfDepthPeelingPerformed=0;
11420   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11421 }
11422
11423 /*!
11424  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11425  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11426  * 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]].
11427  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11428  * A negative value in \b arrIn means that it is ignored.
11429  * 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.
11430  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11431  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11432  * \param [in] arrIn arr origin array from which the extraction will be done.
11433  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11434  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11435  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11436  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11437  * \sa MEDCouplingUMesh::partitionBySpreadZone
11438  */
11439 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11440 {
11441   nbOfDepthPeelingPerformed=0;
11442   if(!arrIndxIn)
11443     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11444   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11445   if(nbOfTuples<=0)
11446     {
11447       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11448       return ret;
11449     }
11450   //
11451   std::vector<bool> fetched(nbOfTuples,false);
11452   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11453 }
11454
11455 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11456 {
11457   nbOfDepthPeelingPerformed=0;
11458   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11459     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11460   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11461   std::vector<bool> fetched2(nbOfTuples,false);
11462   int i=0;
11463   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11464     {
11465       if(*seedElt>=0 && *seedElt<nbOfTuples)
11466         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11467       else
11468         { 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()); }
11469     }
11470   const int *arrInPtr=arrIn->getConstPointer();
11471   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11472   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11473   std::vector<int> idsToFetch1(seedBg,seedEnd);
11474   std::vector<int> idsToFetch2;
11475   std::vector<int> *idsToFetch=&idsToFetch1;
11476   std::vector<int> *idsToFetchOther=&idsToFetch2;
11477   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11478     {
11479       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11480         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11481           if(!fetched[*it2])
11482             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11483       std::swap(idsToFetch,idsToFetchOther);
11484       idsToFetchOther->clear();
11485       nbOfDepthPeelingPerformed++;
11486     }
11487   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11488   i=0;
11489   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11490   int *retPtr=ret->getPointer();
11491   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11492     if(*it)
11493       *retPtr++=i;
11494   return ret.retn();
11495 }
11496
11497 /*!
11498  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11499  * 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
11500  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11501  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11502  *
11503  * \param [in] start begin of set of ids of the input extraction (included)
11504  * \param [in] end end of set of ids of the input extraction (excluded)
11505  * \param [in] step step of the set of ids in range mode.
11506  * \param [in] arrIn arr origin array from which the extraction will be done.
11507  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11508  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11509  * \param [in] srcArrIndex index array of \b srcArr
11510  * \param [out] arrOut the resulting array
11511  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11512  * 
11513  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11514  */
11515 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11516                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11517                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11518 {
11519   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11520     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
11521   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11522   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11523   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11524   int offset=0;
11525   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11526   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11527   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
11528   int it=start;
11529   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11530     {
11531       if(it>=0 && it<nbOfTuples)
11532         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11533       else
11534         {
11535           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11536           throw INTERP_KERNEL::Exception(oss.str());
11537         }
11538     }
11539   srcArrIndexPtr=srcArrIndex->getConstPointer();
11540   arrIo->alloc(nbOfTuples+1,1);
11541   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11542   const int *arrInPtr=arrIn->getConstPointer();
11543   const int *srcArrPtr=srcArr->getConstPointer();
11544   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11545   int *arroPtr=arro->getPointer();
11546   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11547     {
11548       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11549       if(pos<0)
11550         {
11551           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11552           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11553         }
11554       else
11555         {
11556           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11557           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11558         }
11559     }
11560   arrOut=arro.retn();
11561   arrIndexOut=arrIo.retn();
11562 }
11563
11564 /*!
11565  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11566  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11567  *
11568  * \param [in] start begin of set of ids of the input extraction (included)
11569  * \param [in] end end of set of ids of the input extraction (excluded)
11570  * \param [in] step step of the set of ids in range mode.
11571  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11572  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11573  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11574  * \param [in] srcArrIndex index array of \b srcArr
11575  * 
11576  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11577  */
11578 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11579                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11580 {
11581   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
11583   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11584   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11585   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11586   int *arrInOutPtr=arrInOut->getPointer();
11587   const int *srcArrPtr=srcArr->getConstPointer();
11588   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
11589   int it=start;
11590   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11591     {
11592       if(it>=0 && it<nbOfTuples)
11593         {
11594           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11595             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11596           else
11597             {
11598               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11599               throw INTERP_KERNEL::Exception(oss.str());
11600             }
11601         }
11602       else
11603         {
11604           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11605           throw INTERP_KERNEL::Exception(oss.str());
11606         }
11607     }
11608 }
11609
11610 /*!
11611  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11612  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11613  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11614  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11615  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11616  * 
11617  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11618  */
11619 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11620 {
11621   checkFullyDefined();
11622   int mdim=getMeshDimension();
11623   int spaceDim=getSpaceDimension();
11624   if(mdim!=spaceDim)
11625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11626   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11627   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11628   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
11629   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11630   ret->setCoords(getCoords());
11631   ret->allocateCells((int)partition.size());
11632   //
11633   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11634     {
11635       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11636       MCAuto<DataArrayInt> cell;
11637       switch(mdim)
11638       {
11639         case 2:
11640           cell=tmp->buildUnionOf2DMesh();
11641           break;
11642         case 3:
11643           cell=tmp->buildUnionOf3DMesh();
11644           break;
11645         default:
11646           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11647       }
11648
11649       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11650     }
11651   //
11652   ret->finishInsertingCells();
11653   return ret.retn();
11654 }
11655
11656 /*!
11657  * This method partitions \b this into contiguous zone.
11658  * This method only needs a well defined connectivity. Coordinates are not considered here.
11659  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11660  */
11661 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11662 {
11663   int nbOfCellsCur=getNumberOfCells();
11664   std::vector<DataArrayInt *> ret;
11665   if(nbOfCellsCur<=0)
11666     return ret;
11667   DataArrayInt *neigh=0,*neighI=0;
11668   computeNeighborsOfCells(neigh,neighI);
11669   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11670   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11671   std::vector< MCAuto<DataArrayInt> > ret2;
11672   int seed=0;
11673   while(seed<nbOfCellsCur)
11674     {
11675       int nbOfPeelPerformed=0;
11676       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11677       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11678     }
11679   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11680     ret.push_back((*it).retn());
11681   return ret;
11682 }
11683
11684 /*!
11685  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11686  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11687  *
11688  * \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.
11689  * \return a newly allocated DataArrayInt to be managed by the caller.
11690  * \throw In case of \a code has not the right format (typically of size 3*n)
11691  */
11692 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11693 {
11694   MCAuto<DataArrayInt> ret=DataArrayInt::New();
11695   std::size_t nb=code.size()/3;
11696   if(code.size()%3!=0)
11697     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11698   ret->alloc((int)nb,2);
11699   int *retPtr=ret->getPointer();
11700   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11701     {
11702       retPtr[0]=code[3*i+2];
11703       retPtr[1]=code[3*i+2]+code[3*i+1];
11704     }
11705   return ret.retn();
11706 }
11707
11708 /*!
11709  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11710  * All cells in \a this are expected to be linear 3D cells.
11711  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11712  * It leads to an increase to number of cells.
11713  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11714  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11715  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11716  *
11717  * \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.
11718  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11719  * \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. 
11720  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11721  *          an id of old cell producing it. The caller is to delete this array using
11722  *         decrRef() as it is no more needed.
11723  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11724  *
11725  * \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
11726  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11727  * 
11728  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11729  * \throw If \a this is not fully constituted with linear 3D cells.
11730  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11731  */
11732 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11733 {
11734   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11735   checkConnectivityFullyDefined();
11736   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11737     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11738   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11739   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11740   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11741   int *retPt(ret->getPointer());
11742   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11743   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11744   const int *oldc(_nodal_connec->begin());
11745   const int *oldci(_nodal_connec_index->begin());
11746   const double *coords(_coords->begin());
11747   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11748     {
11749       std::vector<int> a; std::vector<double> b;
11750       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11751       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11752       const int *aa(&a[0]);
11753       if(!b.empty())
11754         {
11755           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11756             if(*it<0)
11757               *it=(-(*(it))-1+nbNodes);
11758           addPts->insertAtTheEnd(b.begin(),b.end());
11759           nbNodes+=(int)b.size()/3;
11760         }
11761       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11762         newConn->insertAtTheEnd(aa,aa+4);
11763     }
11764   if(!addPts->empty())
11765     {
11766       addPts->rearrange(3);
11767       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11768       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11769       ret0->setCoords(addPts);
11770     }
11771   else
11772     {
11773       nbOfAdditionalPoints=0;
11774       ret0->setCoords(getCoords());
11775     }
11776   ret0->setNodalConnectivity(newConn);
11777   //
11778   ret->computeOffsetsFull();
11779   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11780   return ret0.retn();
11781 }
11782
11783 /*!
11784  * 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). 
11785  *
11786  * \sa MEDCouplingUMesh::split2DCells
11787  */
11788 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11789 {
11790   checkConnectivityFullyDefined();
11791   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+subNodesInSeg->getNumberOfTuples());
11792   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11793   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11794   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11795   int prevPosOfCi(ciPtr[0]);
11796   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11797     {
11798       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11799       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11800       for(int j=0;j<sz;j++)
11801         {
11802           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11803           for(int k=0;k<sz2;k++)
11804             *cPtr++=subPtr[offset2+k];
11805           if(j!=sz-1)
11806             *cPtr++=oldConn[prevPosOfCi+j+2];
11807           deltaSz+=sz2;
11808         }
11809       prevPosOfCi=ciPtr[1];
11810       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11811     }
11812   if(c->end()!=cPtr)
11813     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11814   _nodal_connec->decrRef();
11815   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11816 }
11817
11818 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11819 {
11820   if(id!=-1)
11821     return id;
11822   else
11823     {
11824       int ret(nodesCnter++);
11825       double newPt[2];
11826       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11827       addCoo.insertAtTheEnd(newPt,newPt+2);
11828       return ret;
11829     }
11830 }
11831
11832 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11833 {
11834   if(id!=-1)
11835     return id;
11836   else
11837     {
11838       int ret(nodesCnter++);
11839       double newPt[2];
11840       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11841       addCoo.insertAtTheEnd(newPt,newPt+2);
11842       return ret;
11843     }
11844 }
11845
11846
11847 /// @cond INTERNAL
11848
11849 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)
11850 {
11851   int tmp[3];
11852   int trueStart(start>=0?start:nbOfEdges+start);
11853   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11854   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11855   if(linOrArc)
11856     {
11857       if(stp-start>1)
11858         {
11859           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11860           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11861           middles.push_back(tmp3+offset);
11862         }
11863       else
11864         middles.push_back(connBg[trueStart+nbOfEdges]);
11865     }
11866 }
11867
11868 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)
11869 {
11870   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11871   newConnOfCell->pushBackSilent(tmpEnd);
11872   if(linOrArc)
11873     {
11874       if(stp-start>1)
11875         {
11876           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11877           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11878           middles.push_back(tmp3+offset);
11879         }
11880       else
11881         middles.push_back(connBg[start+nbOfEdges]);
11882     }
11883 }
11884
11885 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)
11886 {
11887   // only the quadratic point to deal with:
11888   if(linOrArc)
11889     {
11890       if(stp-start>1)
11891         {
11892           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11893           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11894           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11895           middles.push_back(tmp3+offset);
11896         }
11897       else
11898         middles.push_back(connBg[start+nbOfEdges]);
11899     }
11900 }
11901
11902 /// @endcond
11903
11904 /*!
11905  * 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 ) .
11906  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11907  */
11908 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11909 {
11910   std::size_t sz(std::distance(connBg,connEnd));
11911   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11912     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11913   sz--;
11914   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11915   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11916   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11917   unsigned nbOfHit(0); // number of fusions operated
11918   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11919   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
11920   INTERP_KERNEL::NormalizedCellType typeOfSon;
11921   std::vector<int> middles;
11922   bool ret(false);
11923   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11924     {
11925       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11926       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
11927       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11928       posEndElt = posBaseElt+1;
11929
11930       // Look backward first: are the final edges of the cells colinear with the first ones?
11931       // This initializes posBaseElt.
11932       if(nbOfTurn==0)
11933         {
11934           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11935             {
11936               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11937               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11938               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11939               bool isColinear=eint->areColinears();
11940               if(isColinear)
11941                 {
11942                   nbOfHit++;
11943                   posBaseElt--;
11944                   ret=true;
11945                 }
11946               delete eint;
11947               eCand->decrRef();
11948               if(!isColinear)
11949                 break;
11950             }
11951         }
11952       // Now move forward:
11953       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11954       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11955         {
11956           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11957           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11958           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11959           bool isColinear(eint->areColinears());
11960           if(isColinear)
11961             {
11962               nbOfHit++;
11963               posEndElt++;
11964               ret=true;
11965             }
11966           delete eint;
11967           eCand->decrRef();
11968           if(!isColinear)
11969               break;
11970         }
11971       //push [posBaseElt,posEndElt) in newConnOfCell using e
11972       // 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!
11973       if(nbOfTurn==0)
11974         // at the begining of the connectivity (insert type)
11975         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11976       else if((nbOfHit+nbOfTurn) != (nbs-1))
11977         // in the middle
11978         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11979       if ((nbOfHit+nbOfTurn) == (nbs-1))
11980         // at the end (only quad points to deal with)
11981         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11982       posBaseElt=posEndElt;
11983       e->decrRef();
11984     }
11985   if(!middles.empty())
11986     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11987   return ret;
11988 }
11989
11990 /*!
11991  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11992  *
11993  * \return  int - the number of new nodes created.
11994  * \sa MEDCouplingUMesh::split2DCells
11995  */
11996 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11997 {
11998   checkConsistencyLight();
11999   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
12000   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
12001   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
12002   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
12003   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
12004   const double *oldCoordsPtr(getCoords()->begin());
12005   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
12006   int prevPosOfCi(ciPtr[0]);
12007   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
12008     {
12009       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
12010       for(int j=0;j<sz;j++)
12011         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
12012       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
12013       for(int j=0;j<sz;j++)//loop over subedges of oldConn
12014         {
12015           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
12016           if(sz2==0)
12017             {
12018               if(j<sz-1)
12019                 cPtr[1]=oldConn[prevPosOfCi+2+j];
12020               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
12021               continue;
12022             }
12023           std::vector<INTERP_KERNEL::Node *> ns(3);
12024           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
12025           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
12026           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
12027           MCAuto<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
12028           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
12029             {
12030               cPtr[1]=subPtr[offset2+k];
12031               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
12032             }
12033           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
12034           if(j!=sz-1)
12035             { cPtr[1]=tmpEnd; }
12036           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
12037         }
12038       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
12039       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
12040     }
12041   if(c->end()!=cPtr)
12042     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
12043   _nodal_connec->decrRef();
12044   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
12045   addCoo->rearrange(2);
12046   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
12047   setCoords(coo);
12048   return addCoo->getNumberOfTuples();
12049 }
12050
12051 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
12052 {
12053   if(nodalConnec && nodalConnecIndex)
12054     {
12055       types.clear();
12056       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
12057       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
12058       if(nbOfElem>0)
12059         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
12060           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
12061     }
12062 }
12063
12064 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
12065     _own_cell(true),_cell_id(-1),_nb_cell(0)
12066 {
12067   if(mesh)
12068     {
12069       mesh->incrRef();
12070       _nb_cell=mesh->getNumberOfCells();
12071     }
12072 }
12073
12074 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
12075 {
12076   if(_mesh)
12077     _mesh->decrRef();
12078   if(_own_cell)
12079     delete _cell;
12080 }
12081
12082 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
12083     _own_cell(false),_cell_id(bg-1),
12084     _nb_cell(end)
12085 {
12086   if(mesh)
12087     mesh->incrRef();
12088 }
12089
12090 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
12091 {
12092   _cell_id++;
12093   if(_cell_id<_nb_cell)
12094     {
12095       _cell->next();
12096       return _cell;
12097     }
12098   else
12099     return 0;
12100 }
12101
12102 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
12103 {
12104   if(_mesh)
12105     _mesh->incrRef();
12106 }
12107
12108 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
12109 {
12110   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
12111 }
12112
12113 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
12114 {
12115   if(_mesh)
12116     _mesh->decrRef();
12117 }
12118
12119 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
12120     _itc(itc),
12121     _bg(bg),_end(end)
12122 {
12123   if(_mesh)
12124     _mesh->incrRef();
12125 }
12126
12127 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
12128 {
12129   if(_mesh)
12130     _mesh->decrRef();
12131 }
12132
12133 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
12134 {
12135   return _type;
12136 }
12137
12138 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
12139 {
12140   return _end-_bg;
12141 }
12142
12143 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
12144 {
12145   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
12146 }
12147
12148 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
12149 {
12150   if(mesh)
12151     {
12152       mesh->incrRef();
12153       _nb_cell=mesh->getNumberOfCells();
12154     }
12155 }
12156
12157 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
12158 {
12159   if(_mesh)
12160     _mesh->decrRef();
12161   delete _cell;
12162 }
12163
12164 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
12165 {
12166   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
12167   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
12168   if(_cell_id<_nb_cell)
12169     {
12170       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
12171       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
12172       int startId=_cell_id;
12173       _cell_id+=nbOfElems;
12174       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
12175     }
12176   else
12177     return 0;
12178 }
12179
12180 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
12181 {
12182   if(mesh)
12183     {
12184       _conn=mesh->getNodalConnectivity()->getPointer();
12185       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
12186     }
12187 }
12188
12189 void MEDCouplingUMeshCell::next()
12190 {
12191   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
12192     {
12193       _conn+=_conn_lgth;
12194       _conn_indx++;
12195     }
12196   _conn_lgth=_conn_indx[1]-_conn_indx[0];
12197 }
12198
12199 std::string MEDCouplingUMeshCell::repr() const
12200 {
12201   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
12202     {
12203       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
12204       oss << " : ";
12205       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
12206       return oss.str();
12207     }
12208   else
12209     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
12210 }
12211
12212 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
12213 {
12214   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
12215     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
12216   else
12217     return INTERP_KERNEL::NORM_ERROR;
12218 }
12219
12220 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
12221 {
12222   lgth=_conn_lgth;
12223   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
12224     return _conn;
12225   else
12226     return 0;
12227 }