]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/MEDCoupling/MEDCouplingUMesh.cxx
Salome HOME
Further "improvement" on duplicateNodesOnM1Group().
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
30 #include "BBTree.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
44
45 #include <sstream>
46 #include <fstream>
47 #include <numeric>
48 #include <cstring>
49 #include <limits>
50 #include <list>
51
52 using namespace ParaMEDMEM;
53
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
55
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
58 MEDCouplingUMesh *MEDCouplingUMesh::New()
59 {
60   return new MEDCouplingUMesh;
61 }
62
63 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
64 {
65   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
66   ret->setName(meshName);
67   ret->setMeshDimension(meshDim);
68   return ret;
69 }
70
71 /*!
72  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
73  * between \a this and the new mesh.
74  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
75  *          delete this mesh using decrRef() as it is no more needed. 
76  */
77 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
78 {
79   return clone(true);
80 }
81
82 /*!
83  * Returns a new MEDCouplingMesh which is a copy of \a this one.
84  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
85  * this mesh are shared by the new mesh.
86  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
87  *          delete this mesh using decrRef() as it is no more needed. 
88  */
89 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
90 {
91   return new MEDCouplingUMesh(*this,recDeepCpy);
92 }
93
94 /*!
95  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
96  * The coordinates are shared between \a this and the returned instance.
97  * 
98  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
99  * \sa MEDCouplingUMesh::deepCpy
100  */
101 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
102 {
103   checkConnectivityFullyDefined();
104   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
106   ret->setConnectivity(c,ci);
107   return ret.retn();
108 }
109
110 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
111 {
112   if(!other)
113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
114   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
115   if(!otherC)
116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
117   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
118   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
119 }
120
121 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
122 {
123   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
124   return ret;
125 }
126
127 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
128 {
129   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
130   ret.push_back(_nodal_connec);
131   ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
247         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
248           {
249             std::ostringstream oss;
250             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
251             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
252             throw INTERP_KERNEL::Exception(oss.str().c_str());
253           }
254       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
255         {
256           int nodeId=*w;
257           if(nodeId>=0)
258             {
259               if(nodeId>=nbOfNodes)
260                 {
261                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
262                   throw INTERP_KERNEL::Exception(oss.str().c_str());
263                 }
264             }
265           else if(nodeId<-1)
266             {
267               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
268               throw INTERP_KERNEL::Exception(oss.str().c_str());
269             }
270           else
271             {
272               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
273                 {
274                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
275                   throw INTERP_KERNEL::Exception(oss.str().c_str());
276                 }
277             }
278         }
279     }
280 }
281
282
283 /*!
284  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
285  * then \a this mesh is most probably is writable, exchangeable and available for all
286  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
287  *  \param [in] eps - a not used parameter.
288  *  \throw If the mesh dimension is not set.
289  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
290  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
291  *  \throw If the connectivity data array has more than one component.
292  *  \throw If the connectivity data array has a named component.
293  *  \throw If the connectivity index data array has more than one component.
294  *  \throw If the connectivity index data array has a named component.
295  *  \throw If number of nodes defining an element does not correspond to the type of element.
296  *  \throw If the nodal connectivity includes an invalid node id.
297  */
298 void MEDCouplingUMesh::checkCoherency2(double eps) const
299 {
300   checkCoherency1(eps);
301 }
302
303 /*!
304  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
305  * elements contained in the mesh. For more info on the mesh dimension see
306  * \ref MEDCouplingUMeshPage.
307  *  \param [in] meshDim - a new mesh dimension.
308  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
309  */
310 void MEDCouplingUMesh::setMeshDimension(int meshDim)
311 {
312   if(meshDim<-1 || meshDim>3)
313     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
314   _mesh_dim=meshDim;
315   declareAsNew();
316 }
317
318 /*!
319  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
320  * 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.
321  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
322  *
323  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
324  *
325  *  \if ENABLE_EXAMPLES
326  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
328  *  \endif
329  */
330 void MEDCouplingUMesh::allocateCells(int nbOfCells)
331 {
332   if(nbOfCells<0)
333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
334   if(_nodal_connec_index)
335     {
336       _nodal_connec_index->decrRef();
337     }
338   if(_nodal_connec)
339     {
340       _nodal_connec->decrRef();
341     }
342   _nodal_connec_index=DataArrayInt::New();
343   _nodal_connec_index->reserve(nbOfCells+1);
344   _nodal_connec_index->pushBackSilent(0);
345   _nodal_connec=DataArrayInt::New();
346   _nodal_connec->reserve(2*nbOfCells);
347   _types.clear();
348   declareAsNew();
349 }
350
351 /*!
352  * Appends a cell to the connectivity array. For deeper understanding what is
353  * happening see \ref MEDCouplingUMeshNodalConnectivity.
354  *  \param [in] type - type of cell to add.
355  *  \param [in] size - number of nodes constituting this cell.
356  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
357  * 
358  *  \if ENABLE_EXAMPLES
359  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
360  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
361  *  \endif
362  */
363 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
364 {
365   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
366   if(_nodal_connec_index==0)
367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
368   if((int)cm.getDimension()==_mesh_dim)
369     {
370       if(!cm.isDynamic())
371         if(size!=(int)cm.getNumberOfNodes())
372           {
373             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
374             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
375             throw INTERP_KERNEL::Exception(oss.str().c_str());
376           }
377       int idx=_nodal_connec_index->back();
378       int val=idx+size+1;
379       _nodal_connec_index->pushBackSilent(val);
380       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
381       _types.insert(type);
382     }
383   else
384     {
385       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
386       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
387       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
388       throw INTERP_KERNEL::Exception(oss.str().c_str());
389     }
390 }
391
392 /*!
393  * Compacts data arrays to release unused memory. This method is to be called after
394  * finishing cell insertion using \a this->insertNextCell().
395  * 
396  *  \if ENABLE_EXAMPLES
397  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
398  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
399  *  \endif
400  */
401 void MEDCouplingUMesh::finishInsertingCells()
402 {
403   _nodal_connec->pack();
404   _nodal_connec_index->pack();
405   _nodal_connec->declareAsNew();
406   _nodal_connec_index->declareAsNew();
407   updateTime();
408 }
409
410 /*!
411  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
412  * Useful for python users.
413  */
414 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
415 {
416   return new MEDCouplingUMeshCellIterator(this);
417 }
418
419 /*!
420  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
421  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
422  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
423  * Useful for python users.
424  */
425 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
426 {
427   if(!checkConsecutiveCellTypes())
428     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
429   return new MEDCouplingUMeshCellByTypeEntry(this);
430 }
431
432 /*!
433  * Returns a set of all cell types available in \a this mesh.
434  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
435  * \warning this method does not throw any exception even if \a this is not defined.
436  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
437  */
438 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
439 {
440   return _types;
441 }
442
443 /*!
444  * This method returns the sorted list of geometric types in \a this.
445  * 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
446  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
447  *
448  * \throw if connectivity in \a this is not correctly defined.
449  *  
450  * \sa MEDCouplingMesh::getAllGeoTypes
451  */
452 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
453 {
454   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
455   checkConnectivityFullyDefined();
456   int nbOfCells(getNumberOfCells());
457   if(nbOfCells==0)
458     return ret;
459   if(getMeshLength()<1)
460     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
461   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
462   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
463   for(int i=1;i<nbOfCells;i++,ci++)
464     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
465       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
466   return ret;
467 }
468
469 /*!
470  * This method is a method that compares \a this and \a other.
471  * This method compares \b all attributes, even names and component names.
472  */
473 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
474 {
475   if(!other)
476     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
477   std::ostringstream oss; oss.precision(15);
478   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
479   if(!otherC)
480     {
481       reason="mesh given in input is not castable in MEDCouplingUMesh !";
482       return false;
483     }
484   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
485     return false;
486   if(_mesh_dim!=otherC->_mesh_dim)
487     {
488       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
489       reason=oss.str();
490       return false;
491     }
492   if(_types!=otherC->_types)
493     {
494       oss << "umesh geometric type mismatch :\nThis geometric types are :";
495       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
496         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
497       oss << "\nOther geometric types are :";
498       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
499         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
500       reason=oss.str();
501       return false;
502     }
503   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
504     if(_nodal_connec==0 || otherC->_nodal_connec==0)
505       {
506         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
507         return false;
508       }
509   if(_nodal_connec!=otherC->_nodal_connec)
510     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
511       {
512         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
513         return false;
514       }
515   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
516     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
517       {
518         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
519         return false;
520       }
521   if(_nodal_connec_index!=otherC->_nodal_connec_index)
522     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
523       {
524         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
525         return false;
526       }
527   return true;
528 }
529
530 /*!
531  * Checks if data arrays of this mesh (node coordinates, nodal
532  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
533  * not considered.
534  *  \param [in] other - the mesh to compare with.
535  *  \param [in] prec - precision value used to compare node coordinates.
536  *  \return bool - \a true if the two meshes are same.
537  */
538 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
539 {
540   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
541   if(!otherC)
542     return false;
543   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
544     return false;
545   if(_mesh_dim!=otherC->_mesh_dim)
546     return false;
547   if(_types!=otherC->_types)
548     return false;
549   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
550     if(_nodal_connec==0 || otherC->_nodal_connec==0)
551       return false;
552   if(_nodal_connec!=otherC->_nodal_connec)
553     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
554       return false;
555   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
556     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
557       return false;
558   if(_nodal_connec_index!=otherC->_nodal_connec_index)
559     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
560       return false;
561   return true;
562 }
563
564 /*!
565  * Checks if \a this and \a other meshes are geometrically equivalent with high
566  * probability, else an exception is thrown. The meshes are considered equivalent if
567  * (1) meshes contain the same number of nodes and the same number of elements of the
568  * same types (2) three cells of the two meshes (first, last and middle) are based
569  * on coincident nodes (with a specified precision).
570  *  \param [in] other - the mesh to compare with.
571  *  \param [in] prec - the precision used to compare nodes of the two meshes.
572  *  \throw If the two meshes do not match.
573  */
574 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
575 {
576   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
577   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
578   if(!otherC)
579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
580 }
581
582 /*!
583  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
584  * cells each node belongs to.
585  * \warning For speed reasons, this method does not check if node ids in the nodal
586  *          connectivity correspond to the size of node coordinates array.
587  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
588  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
589  *        dividing cell ids in \a revNodal into groups each referring to one
590  *        node. Its every element (except the last one) is an index pointing to the
591  *         first id of a group of cells. For example cells sharing the node #1 are 
592  *        described by following range of indices: 
593  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
594  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
595  *        Number of cells sharing the *i*-th node is
596  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
597  * \throw If the coordinates array is not set.
598  * \throw If the nodal connectivity of cells is not defined.
599  * 
600  * \if ENABLE_EXAMPLES
601  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
602  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
603  * \endif
604  */
605 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
606 {
607   checkFullyDefined();
608   int nbOfNodes=getNumberOfNodes();
609   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
610   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
611   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
612   const int *conn=_nodal_connec->getConstPointer();
613   const int *connIndex=_nodal_connec_index->getConstPointer();
614   int nbOfCells=getNumberOfCells();
615   int nbOfEltsInRevNodal=0;
616   for(int eltId=0;eltId<nbOfCells;eltId++)
617     {
618       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
619       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
620       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
621         if(*iter>=0)//for polyhedrons
622           {
623             nbOfEltsInRevNodal++;
624             revNodalIndxPtr[(*iter)+1]++;
625           }
626     }
627   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
628   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
629   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
630   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
631   for(int eltId=0;eltId<nbOfCells;eltId++)
632     {
633       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
634       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
635       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
636         if(*iter>=0)//for polyhedrons
637           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
638     }
639 }
640
641 /// @cond INTERNAL
642
643 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
644 {
645   return id;
646 }
647
648 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
649 {
650   if(!compute)
651     return id+1;
652   else
653     {
654       if(cm.getOrientationStatus(nb,conn1,conn2))
655         return id+1;
656       else
657         return -(id+1);
658     }
659 }
660
661 class MinusOneSonsGenerator
662 {
663 public:
664   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
665   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
666   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
667   static const int DELTA=1;
668 private:
669   const INTERP_KERNEL::CellModel& _cm;
670 };
671
672 class MinusOneSonsGeneratorBiQuadratic
673 {
674 public:
675   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
676   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
677   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
678   static const int DELTA=1;
679 private:
680   const INTERP_KERNEL::CellModel& _cm;
681 };
682
683 class MinusTwoSonsGenerator
684 {
685 public:
686   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
687   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
688   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
689   static const int DELTA=2;
690 private:
691   const INTERP_KERNEL::CellModel& _cm;
692 };
693
694 /// @endcond
695
696 /*!
697  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
698  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
699  * describing correspondence between cells of \a this and the result meshes are
700  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
701  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
702  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
703  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
704  * \warning For speed reasons, this method does not check if node ids in the nodal
705  *          connectivity correspond to the size of node coordinates array.
706  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
707  *          to write this mesh to the MED file, its cells must be sorted using
708  *          sortCellsInMEDFileFrmt().
709  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
710  *         each cell of \a this mesh.
711  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
712  *        dividing cell ids in \a desc into groups each referring to one
713  *        cell of \a this mesh. Its every element (except the last one) is an index
714  *        pointing to the first id of a group of cells. For example cells of the
715  *        result mesh bounding the cell #1 of \a this mesh are described by following
716  *        range of indices:
717  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
718  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
719  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
720  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
721  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
722  *         by each cell of the result mesh.
723  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
724  *        in the result mesh,
725  *        dividing cell ids in \a revDesc into groups each referring to one
726  *        cell of the result mesh the same way as \a descIndx divides \a desc.
727  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
728  *        delete this mesh using decrRef() as it is no more needed.
729  *  \throw If the coordinates array is not set.
730  *  \throw If the nodal connectivity of cells is node defined.
731  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
732  *         revDescIndx == NULL.
733  * 
734  *  \if ENABLE_EXAMPLES
735  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
736  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
737  *  \endif
738  * \sa buildDescendingConnectivity2()
739  */
740 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
741 {
742   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
743 }
744
745 /*!
746  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
747  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
748  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
749  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
750  * \sa MEDCouplingUMesh::buildDescendingConnectivity
751  */
752 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
753 {
754   checkFullyDefined();
755   if(getMeshDimension()!=3)
756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
757   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
758 }
759
760 /*!
761  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
762  * this->getMeshDimension(), that bound cells of \a this mesh. In
763  * addition arrays describing correspondence between cells of \a this and the result
764  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
765  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
766  *  mesh. This method differs from buildDescendingConnectivity() in that apart
767  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
768  * result meshes. So a positive id means that order of nodes in corresponding cells
769  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
770  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
771  * i.e. cell ids are one-based.
772  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
773  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
774  * \warning For speed reasons, this method does not check if node ids in the nodal
775  *          connectivity correspond to the size of node coordinates array.
776  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
777  *          to write this mesh to the MED file, its cells must be sorted using
778  *          sortCellsInMEDFileFrmt().
779  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
780  *         each cell of \a this mesh.
781  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
782  *        dividing cell ids in \a desc into groups each referring to one
783  *        cell of \a this mesh. Its every element (except the last one) is an index
784  *        pointing to the first id of a group of cells. For example cells of the
785  *        result mesh bounding the cell #1 of \a this mesh are described by following
786  *        range of indices:
787  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
788  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
789  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
790  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
791  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
792  *         by each cell of the result mesh.
793  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
794  *        in the result mesh,
795  *        dividing cell ids in \a revDesc into groups each referring to one
796  *        cell of the result mesh the same way as \a descIndx divides \a desc.
797  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
798  *        shares the node coordinates array with \a this mesh. The caller is to
799  *        delete this mesh using decrRef() as it is no more needed.
800  *  \throw If the coordinates array is not set.
801  *  \throw If the nodal connectivity of cells is node defined.
802  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
803  *         revDescIndx == NULL.
804  * 
805  *  \if ENABLE_EXAMPLES
806  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
807  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
808  *  \endif
809  * \sa buildDescendingConnectivity()
810  */
811 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
812 {
813   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
814 }
815
816 /*!
817  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
819  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
820  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
821  *
822  * \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
823  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
824  * \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.
825  */
826 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
827 {
828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
832   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
833   meshDM1=0;
834   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
835 }
836
837 /*!
838  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
839  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
840  * excluding a set of meshdim-1 cells in input descending connectivity.
841  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
842  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
843  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
844  *
845  * \param [in] desc descending connectivity array.
846  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
847  * \param [in] revDesc reverse descending connectivity array.
848  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
849  * \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
850  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
851  * \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.
852  */
853 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
854                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
855 {
856   if(!desc || !descIndx || !revDesc || !revDescIndx)
857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
858   const int *descPtr=desc->getConstPointer();
859   const int *descIPtr=descIndx->getConstPointer();
860   const int *revDescPtr=revDesc->getConstPointer();
861   const int *revDescIPtr=revDescIndx->getConstPointer();
862   //
863   int nbCells=descIndx->getNumberOfTuples()-1;
864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
866   int *out1Ptr=out1->getPointer();
867   *out1Ptr++=0;
868   out0->reserve(desc->getNumberOfTuples());
869   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
870     {
871       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
872         {
873           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
874           s.erase(i);
875           out0->insertAtTheEnd(s.begin(),s.end());
876         }
877       *out1Ptr=out0->getNumberOfTuples();
878     }
879   neighbors=out0.retn();
880   neighborsIndx=out1.retn();
881 }
882
883 /*!
884  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
885  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
886  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
887  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
888  *
889  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
890  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
891  * \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.
892  */
893 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
894 {
895   checkFullyDefined();
896   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
897   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
898   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
899   switch(mdim)
900   {
901     case 3:
902       {
903         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
904         break;
905       }
906     case 2:
907       {
908         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
909         break;
910       }
911     case 1:
912       {
913         mesh1D=const_cast<MEDCouplingUMesh *>(this);
914         mesh1D->incrRef();
915         break;
916       }
917     default:
918       {
919         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
920       }
921   }
922   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
923   mesh1D->getReverseNodalConnectivity(desc,descIndx);
924   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
925   ret0->alloc(desc->getNumberOfTuples(),1);
926   int *r0Pt(ret0->getPointer());
927   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
928   for(int i=0;i<nbNodes;i++,rni++)
929     {
930       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
931         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
932     }
933   neighbors=ret0.retn();
934   neighborsIdx=descIndx.retn();
935 }
936
937 /// @cond INTERNAL
938
939 /*!
940  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
941  * For speed reasons no check of this will be done.
942  */
943 template<class SonsGenerator>
944 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
945 {
946   if(!desc || !descIndx || !revDesc || !revDescIndx)
947     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
948   checkConnectivityFullyDefined();
949   int nbOfCells=getNumberOfCells();
950   int nbOfNodes=getNumberOfNodes();
951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
952   int *revNodalIndxPtr=revNodalIndx->getPointer();
953   const int *conn=_nodal_connec->getConstPointer();
954   const int *connIndex=_nodal_connec_index->getConstPointer();
955   std::string name="Mesh constituent of "; name+=getName();
956   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
957   ret->setCoords(getCoords());
958   ret->allocateCells(2*nbOfCells);
959   descIndx->alloc(nbOfCells+1,1);
960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
961   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
962   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
963     {
964       int pos=connIndex[eltId];
965       int posP1=connIndex[eltId+1];
966       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
967       SonsGenerator sg(cm);
968       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
969       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
970       for(unsigned i=0;i<nbOfSons;i++)
971         {
972           INTERP_KERNEL::NormalizedCellType cmsId;
973           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
974           for(unsigned k=0;k<nbOfNodesSon;k++)
975             if(tmp[k]>=0)
976               revNodalIndxPtr[tmp[k]+1]++;
977           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
978           revDesc2->pushBackSilent(eltId);
979         }
980       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
981     }
982   int nbOfCellsM1=ret->getNumberOfCells();
983   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
985   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
986   int *revNodalPtr=revNodal->getPointer();
987   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
988   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
989   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
990     {
991       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
992       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
993       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
994         if(*iter>=0)//for polyhedrons
995           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
996     }
997   //
998   DataArrayInt *commonCells=0,*commonCellsI=0;
999   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1001   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1002   int newNbOfCellsM1=-1;
1003   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1004                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1005   std::vector<bool> isImpacted(nbOfCellsM1,false);
1006   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1007     for(int work2=work[0];work2!=work[1];work2++)
1008       isImpacted[commonCellsPtr[work2]]=true;
1009   const int *o2nM1Ptr=o2nM1->getConstPointer();
1010   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1011   const int *n2oM1Ptr=n2oM1->getConstPointer();
1012   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1013   ret2->copyTinyInfoFrom(this);
1014   desc->alloc(descIndx->back(),1);
1015   int *descPtr=desc->getPointer();
1016   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1017   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1018     {
1019       if(!isImpacted[i])
1020         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1021       else
1022         {
1023           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1024             {
1025               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1026               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1027             }
1028           else
1029             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1030         }
1031     }
1032   revDesc->reserve(newNbOfCellsM1);
1033   revDescIndx->alloc(newNbOfCellsM1+1,1);
1034   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1035   const int *revDesc2Ptr=revDesc2->getConstPointer();
1036   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1037     {
1038       int oldCellIdM1=n2oM1Ptr[i];
1039       if(!isImpacted[oldCellIdM1])
1040         {
1041           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1042           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1043         }
1044       else
1045         {
1046           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1047             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1048           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1049           commonCellsIPtr++;
1050         }
1051     }
1052   //
1053   return ret2.retn();
1054 }
1055
1056 struct MEDCouplingAccVisit
1057 {
1058   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1059   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1060   int _new_nb_of_nodes;
1061 };
1062
1063 /// @endcond
1064
1065 /*!
1066  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1067  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1068  * array of cell ids. Pay attention that after conversion all algorithms work slower
1069  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1070  * conversion due presence of invalid ids in the array of cells to convert, as a
1071  * result \a this mesh contains some already converted elements. In this case the 2D
1072  * mesh remains valid but 3D mesh becomes \b inconsistent!
1073  *  \warning This method can significantly modify the order of geometric types in \a this,
1074  *          hence, to write this mesh to the MED file, its cells must be sorted using
1075  *          sortCellsInMEDFileFrmt().
1076  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1077  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1078  *         cellIdsToConvertBg.
1079  *  \throw If the coordinates array is not set.
1080  *  \throw If the nodal connectivity of cells is node defined.
1081  *  \throw If dimension of \a this mesh is not either 2 or 3.
1082  *
1083  *  \if ENABLE_EXAMPLES
1084  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1085  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1086  *  \endif
1087  */
1088 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1089 {
1090   checkFullyDefined();
1091   int dim=getMeshDimension();
1092   if(dim<2 || dim>3)
1093     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1094   int nbOfCells(getNumberOfCells());
1095   if(dim==2)
1096     {
1097       const int *connIndex=_nodal_connec_index->getConstPointer();
1098       int *conn=_nodal_connec->getPointer();
1099       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1100         {
1101           if(*iter>=0 && *iter<nbOfCells)
1102             {
1103               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1104               if(!cm.isQuadratic())
1105                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1106               else
1107                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1108             }
1109           else
1110             {
1111               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1112               oss << " in range [0," << nbOfCells << ") !";
1113               throw INTERP_KERNEL::Exception(oss.str().c_str());
1114             }
1115         }
1116     }
1117   else
1118     {
1119       int *connIndex(_nodal_connec_index->getPointer());
1120       const int *connOld(_nodal_connec->getConstPointer());
1121       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1122       std::vector<bool> toBeDone(nbOfCells,false);
1123       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1124         {
1125           if(*iter>=0 && *iter<nbOfCells)
1126             toBeDone[*iter]=true;
1127           else
1128             {
1129               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1130               oss << " in range [0," << nbOfCells << ") !";
1131               throw INTERP_KERNEL::Exception(oss.str().c_str());
1132             }
1133         }
1134       for(int cellId=0;cellId<nbOfCells;cellId++)
1135         {
1136           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1137           int lgthOld(posP1-pos-1);
1138           if(toBeDone[cellId])
1139             {
1140               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1141               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1142               int *tmp(new int[nbOfFaces*lgthOld+1]);
1143               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1144               for(unsigned j=0;j<nbOfFaces;j++)
1145                 {
1146                   INTERP_KERNEL::NormalizedCellType type;
1147                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1148                   work+=offset;
1149                   *work++=-1;
1150                 }
1151               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1152               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1153               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1154               delete [] tmp;
1155             }
1156           else
1157             {
1158               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1159               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1160             }
1161         }
1162       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1163     }
1164   computeTypes();
1165 }
1166
1167 /*!
1168  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1169  * polyhedrons (if \a this is a 3D mesh).
1170  *  \warning As this method is purely for user-friendliness and no optimization is
1171  *          done to avoid construction of a useless vector, this method can be costly
1172  *          in memory.
1173  *  \throw If the coordinates array is not set.
1174  *  \throw If the nodal connectivity of cells is node defined.
1175  *  \throw If dimension of \a this mesh is not either 2 or 3.
1176  */
1177 void MEDCouplingUMesh::convertAllToPoly()
1178 {
1179   int nbOfCells=getNumberOfCells();
1180   std::vector<int> cellIds(nbOfCells);
1181   for(int i=0;i<nbOfCells;i++)
1182     cellIds[i]=i;
1183   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1184 }
1185
1186 /*!
1187  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1188  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1189  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1190  * base facet of the volume and the second half of nodes describes an opposite facet
1191  * having the same number of nodes as the base one. This method converts such
1192  * connectivity to a valid polyhedral format where connectivity of each facet is
1193  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1194  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1195  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1196  * a correct orientation of the first facet of a polyhedron, else orientation of a
1197  * corrected cell is reverse.<br>
1198  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1199  * it releases the user from boring description of polyhedra connectivity in the valid
1200  * format.
1201  *  \throw If \a this->getMeshDimension() != 3.
1202  *  \throw If \a this->getSpaceDimension() != 3.
1203  *  \throw If the nodal connectivity of cells is not defined.
1204  *  \throw If the coordinates array is not set.
1205  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1206  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1207  *
1208  *  \if ENABLE_EXAMPLES
1209  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1210  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1211  *  \endif
1212  */
1213 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1214 {
1215   checkFullyDefined();
1216   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1217     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1218   int nbOfCells=getNumberOfCells();
1219   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1220   newCi->alloc(nbOfCells+1,1);
1221   int *newci=newCi->getPointer();
1222   const int *ci=_nodal_connec_index->getConstPointer();
1223   const int *c=_nodal_connec->getConstPointer();
1224   newci[0]=0;
1225   for(int i=0;i<nbOfCells;i++)
1226     {
1227       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1228       if(type==INTERP_KERNEL::NORM_POLYHED)
1229         {
1230           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1231             {
1232               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1233               throw INTERP_KERNEL::Exception(oss.str().c_str());
1234             }
1235           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1236           if(n2%2!=0)
1237             {
1238               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 !";
1239               throw INTERP_KERNEL::Exception(oss.str().c_str());
1240             }
1241           int n1=(int)(n2/2);
1242           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)
1243         }
1244       else
1245         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1246     }
1247   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1248   newC->alloc(newci[nbOfCells],1);
1249   int *newc=newC->getPointer();
1250   for(int i=0;i<nbOfCells;i++)
1251     {
1252       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1253       if(type==INTERP_KERNEL::NORM_POLYHED)
1254         {
1255           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1256           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1257           *newc++=-1;
1258           for(std::size_t j=0;j<n1;j++)
1259             {
1260               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1261               newc[n1+5*j]=-1;
1262               newc[n1+5*j+1]=c[ci[i]+1+j];
1263               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1264               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1265               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1266             }
1267           newc+=n1*6;
1268         }
1269       else
1270         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1271     }
1272   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1273   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1274 }
1275
1276
1277 /*!
1278  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1279  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1280  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1281  *          to write this mesh to the MED file, its cells must be sorted using
1282  *          sortCellsInMEDFileFrmt().
1283  * \return \c true if at least one cell has been converted, \c false else. In the
1284  *         last case the nodal connectivity remains unchanged.
1285  * \throw If the coordinates array is not set.
1286  * \throw If the nodal connectivity of cells is not defined.
1287  * \throw If \a this->getMeshDimension() < 0.
1288  */
1289 bool MEDCouplingUMesh::unPolyze()
1290 {
1291   checkFullyDefined();
1292   int mdim=getMeshDimension();
1293   if(mdim<0)
1294     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1295   if(mdim<=1)
1296     return false;
1297   int nbOfCells=getNumberOfCells();
1298   if(nbOfCells<1)
1299     return false;
1300   int initMeshLgth=getMeshLength();
1301   int *conn=_nodal_connec->getPointer();
1302   int *index=_nodal_connec_index->getPointer();
1303   int posOfCurCell=0;
1304   int newPos=0;
1305   int lgthOfCurCell;
1306   bool ret=false;
1307   for(int i=0;i<nbOfCells;i++)
1308     {
1309       lgthOfCurCell=index[i+1]-posOfCurCell;
1310       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1311       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1312       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1313       int newLgth;
1314       if(cm.isDynamic())
1315         {
1316           switch(cm.getDimension())
1317           {
1318             case 2:
1319               {
1320                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1321                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1322                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1323                 break;
1324               }
1325             case 3:
1326               {
1327                 int nbOfFaces,lgthOfPolyhConn;
1328                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1329                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1330                 break;
1331               }
1332             case 1:
1333               {
1334                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1335                 break;
1336               }
1337           }
1338           ret=ret || (newType!=type);
1339           conn[newPos]=newType;
1340           newPos+=newLgth+1;
1341           posOfCurCell=index[i+1];
1342           index[i+1]=newPos;
1343         }
1344       else
1345         {
1346           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1347           newPos+=lgthOfCurCell;
1348           posOfCurCell+=lgthOfCurCell;
1349           index[i+1]=newPos;
1350         }
1351     }
1352   if(newPos!=initMeshLgth)
1353     _nodal_connec->reAlloc(newPos);
1354   if(ret)
1355     computeTypes();
1356   return ret;
1357 }
1358
1359 /*!
1360  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1361  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1362  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1363  *
1364  * \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 
1365  *             precision.
1366  */
1367 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1368 {
1369   checkFullyDefined();
1370   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1372   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1373   coords->recenterForMaxPrecision(eps);
1374   //
1375   int nbOfCells=getNumberOfCells();
1376   const int *conn=_nodal_connec->getConstPointer();
1377   const int *index=_nodal_connec_index->getConstPointer();
1378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1379   connINew->alloc(nbOfCells+1,1);
1380   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1382   bool changed=false;
1383   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1384     {
1385       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1386         {
1387           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1388           changed=true;
1389         }
1390       else
1391         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1392       *connINewPtr=connNew->getNumberOfTuples();
1393     }
1394   if(changed)
1395     setConnectivity(connNew,connINew,false);
1396 }
1397
1398 /*!
1399  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1400  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1401  * the format of the returned DataArrayInt instance.
1402  * 
1403  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1404  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1405  */
1406 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1407 {
1408   checkConnectivityFullyDefined();
1409   int nbOfCells=getNumberOfCells();
1410   const int *connIndex=_nodal_connec_index->getConstPointer();
1411   const int *conn=_nodal_connec->getConstPointer();
1412   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1413   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1414   std::vector<bool> retS(maxElt,false);
1415   for(int i=0;i<nbOfCells;i++)
1416     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1417       if(conn[j]>=0)
1418         retS[conn[j]]=true;
1419   int sz=0;
1420   for(int i=0;i<maxElt;i++)
1421     if(retS[i])
1422       sz++;
1423   DataArrayInt *ret=DataArrayInt::New();
1424   ret->alloc(sz,1);
1425   int *retPtr=ret->getPointer();
1426   for(int i=0;i<maxElt;i++)
1427     if(retS[i])
1428       *retPtr++=i;
1429   return ret;
1430 }
1431
1432 /*!
1433  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1434  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1435  */
1436 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1437 {
1438   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1439   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1440   for(int i=0;i<nbOfCells;i++)
1441     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1442       if(conn[j]>=0)
1443         {
1444           if(conn[j]<nbOfNodes)
1445             nodeIdsInUse[conn[j]]=true;
1446           else
1447             {
1448               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1449               throw INTERP_KERNEL::Exception(oss.str().c_str());
1450             }
1451         }
1452 }
1453
1454 /*!
1455  * Finds nodes not used in any cell and returns an array giving a new id to every node
1456  * by excluding the unused nodes, for which the array holds -1. The result array is
1457  * a mapping in "Old to New" mode. 
1458  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1459  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1460  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1461  *          if the node is unused or a new id else. The caller is to delete this
1462  *          array using decrRef() as it is no more needed.  
1463  *  \throw If the coordinates array is not set.
1464  *  \throw If the nodal connectivity of cells is not defined.
1465  *  \throw If the nodal connectivity includes an invalid id.
1466  *
1467  *  \if ENABLE_EXAMPLES
1468  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1469  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1470  *  \endif
1471  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1472  */
1473 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1474 {
1475   nbrOfNodesInUse=-1;
1476   int nbOfNodes(getNumberOfNodes());
1477   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1478   ret->alloc(nbOfNodes,1);
1479   int *traducer=ret->getPointer();
1480   std::fill(traducer,traducer+nbOfNodes,-1);
1481   int nbOfCells=getNumberOfCells();
1482   const int *connIndex=_nodal_connec_index->getConstPointer();
1483   const int *conn=_nodal_connec->getConstPointer();
1484   for(int i=0;i<nbOfCells;i++)
1485     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1486       if(conn[j]>=0)
1487         {
1488           if(conn[j]<nbOfNodes)
1489             traducer[conn[j]]=1;
1490           else
1491             {
1492               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1493               throw INTERP_KERNEL::Exception(oss.str().c_str());
1494             }
1495         }
1496   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1497   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1498   return ret.retn();
1499 }
1500
1501 /*!
1502  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1503  * For each cell in \b this the number of nodes constituting cell is computed.
1504  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1505  * So for pohyhedrons some nodes can be counted several times in the returned result.
1506  * 
1507  * \return a newly allocated array
1508  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1509  */
1510 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1511 {
1512   checkConnectivityFullyDefined();
1513   int nbOfCells=getNumberOfCells();
1514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1515   ret->alloc(nbOfCells,1);
1516   int *retPtr=ret->getPointer();
1517   const int *conn=getNodalConnectivity()->getConstPointer();
1518   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1519   for(int i=0;i<nbOfCells;i++,retPtr++)
1520     {
1521       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1522         *retPtr=connI[i+1]-connI[i]-1;
1523       else
1524         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1525     }
1526   return ret.retn();
1527 }
1528
1529 /*!
1530  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1531  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1532  *
1533  * \return DataArrayInt * - new object to be deallocated by the caller.
1534  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1535  */
1536 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1537 {
1538   checkConnectivityFullyDefined();
1539   int nbOfCells=getNumberOfCells();
1540   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1541   ret->alloc(nbOfCells,1);
1542   int *retPtr=ret->getPointer();
1543   const int *conn=getNodalConnectivity()->getConstPointer();
1544   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1545   for(int i=0;i<nbOfCells;i++,retPtr++)
1546     {
1547       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1548       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1549         *retPtr=(int)s.size();
1550       else
1551         {
1552           s.erase(-1);
1553           *retPtr=(int)s.size();
1554         }
1555     }
1556   return ret.retn();
1557 }
1558
1559 /*!
1560  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1561  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1562  * 
1563  * \return a newly allocated array
1564  */
1565 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1566 {
1567   checkConnectivityFullyDefined();
1568   int nbOfCells=getNumberOfCells();
1569   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1570   ret->alloc(nbOfCells,1);
1571   int *retPtr=ret->getPointer();
1572   const int *conn=getNodalConnectivity()->getConstPointer();
1573   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1574   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1575     {
1576       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1577       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1578     }
1579   return ret.retn();
1580 }
1581
1582 /*!
1583  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1584  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1585  * array mean that the corresponding old node is no more used. 
1586  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1587  *           this->getNumberOfNodes() before call of this method. The caller is to
1588  *           delete this array using decrRef() as it is no more needed. 
1589  *  \throw If the coordinates array is not set.
1590  *  \throw If the nodal connectivity of cells is not defined.
1591  *  \throw If the nodal connectivity includes an invalid id.
1592  *  \sa areAllNodesFetched
1593  *
1594  *  \if ENABLE_EXAMPLES
1595  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1596  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1597  *  \endif
1598  */
1599 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1600 {
1601   return MEDCouplingPointSet::zipCoordsTraducer();
1602 }
1603
1604 /*!
1605  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1606  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1607  */
1608 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1609 {
1610   switch(compType)
1611   {
1612     case 0:
1613       return AreCellsEqual0(conn,connI,cell1,cell2);
1614     case 1:
1615       return AreCellsEqual1(conn,connI,cell1,cell2);
1616     case 2:
1617       return AreCellsEqual2(conn,connI,cell1,cell2);
1618     case 3:
1619       return AreCellsEqual3(conn,connI,cell1,cell2);
1620     case 7:
1621       return AreCellsEqual7(conn,connI,cell1,cell2);
1622   }
1623   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1624 }
1625
1626 /*!
1627  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1628  */
1629 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1630 {
1631   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1632     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1633   return 0;
1634 }
1635
1636 /*!
1637  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1638  */
1639 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1640 {
1641   int sz=connI[cell1+1]-connI[cell1];
1642   if(sz==connI[cell2+1]-connI[cell2])
1643     {
1644       if(conn[connI[cell1]]==conn[connI[cell2]])
1645         {
1646           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1647           unsigned dim=cm.getDimension();
1648           if(dim!=3)
1649             {
1650               if(dim!=1)
1651                 {
1652                   int sz1=2*(sz-1);
1653                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1654                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1655                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1656                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1657                   return work!=tmp+sz1?1:0;
1658                 }
1659               else
1660                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1661             }
1662           else
1663             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1664         }
1665     }
1666   return 0;
1667 }
1668
1669 /*!
1670  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1671  */
1672 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1673 {
1674   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1675     {
1676       if(conn[connI[cell1]]==conn[connI[cell2]])
1677         {
1678           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1679           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1680           return s1==s2?1:0;
1681         }
1682     }
1683   return 0;
1684 }
1685
1686 /*!
1687  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1688  */
1689 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1690 {
1691   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1692     {
1693       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1694       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1695       return s1==s2?1:0;
1696     }
1697   return 0;
1698 }
1699
1700 /*!
1701  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1702  */
1703 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1704 {
1705   int sz=connI[cell1+1]-connI[cell1];
1706   if(sz==connI[cell2+1]-connI[cell2])
1707     {
1708       if(conn[connI[cell1]]==conn[connI[cell2]])
1709         {
1710           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1711           unsigned dim=cm.getDimension();
1712           if(dim!=3)
1713             {
1714               if(dim!=1)
1715                 {
1716                   int sz1=2*(sz-1);
1717                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1718                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1719                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1720                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1721                   if(work!=tmp+sz1)
1722                     return 1;
1723                   else
1724                     {
1725                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1726                       std::reverse_iterator<int *> it2((int *)tmp);
1727                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1728                         return 2;
1729                       else
1730                         return 0;
1731                     }
1732
1733                   return work!=tmp+sz1?1:0;
1734                 }
1735               else
1736                 {//case of SEG2 and SEG3
1737                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1738                     return 1;
1739                   if(!cm.isQuadratic())
1740                     {
1741                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1742                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1743                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1744                         return 2;
1745                       return 0;
1746                     }
1747                   else
1748                     {
1749                       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])
1750                         return 2;
1751                       return 0;
1752                     }
1753                 }
1754             }
1755           else
1756             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1757         }
1758     }
1759   return 0;
1760 }
1761
1762 /*!
1763  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1764  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1765  * and result remains unchanged.
1766  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1767  * If in 'candidates' pool -1 value is considered as an empty value.
1768  * WARNING this method returns only ONE set of result !
1769  */
1770 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1771 {
1772   if(candidates.size()<1)
1773     return false;
1774   bool ret=false;
1775   std::vector<int>::const_iterator iter=candidates.begin();
1776   int start=(*iter++);
1777   for(;iter!=candidates.end();iter++)
1778     {
1779       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1780       if(status!=0)
1781         {
1782           if(!ret)
1783             {
1784               result->pushBackSilent(start);
1785               ret=true;
1786             }
1787           if(status==1)
1788             result->pushBackSilent(*iter);
1789           else
1790             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1791         }
1792     }
1793   return ret;
1794 }
1795
1796 /*!
1797  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1798  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1799  *
1800  * \param [in] compType input specifying the technique used to compare cells each other.
1801  *   - 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.
1802  *   - 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)
1803  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1804  *   - 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
1805  * can be used for users not sensitive to orientation of cell
1806  * \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.
1807  * \param [out] commonCells
1808  * \param [out] commonCellsI
1809  * \return the correspondance array old to new in a newly allocated array.
1810  * 
1811  */
1812 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1813 {
1814   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1815   getReverseNodalConnectivity(revNodal,revNodalI);
1816   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1817 }
1818
1819 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1820                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1821 {
1822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1823   int nbOfCells=nodalI->getNumberOfTuples()-1;
1824   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1825   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1826   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1827   std::vector<bool> isFetched(nbOfCells,false);
1828   if(startCellId==0)
1829     {
1830       for(int i=0;i<nbOfCells;i++)
1831         {
1832           if(!isFetched[i])
1833             {
1834               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1835               std::vector<int> v,v2;
1836               if(connOfNode!=connPtr+connIPtr[i+1])
1837                 {
1838                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1839                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1840                   connOfNode++;
1841                 }
1842               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1843                 if(*connOfNode>=0)
1844                   {
1845                     v=v2;
1846                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1847                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1848                     v2.resize(std::distance(v2.begin(),it));
1849                   }
1850               if(v2.size()>1)
1851                 {
1852                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1853                     {
1854                       int pos=commonCellsI->back();
1855                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1856                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1857                         isFetched[*it]=true;
1858                     }
1859                 }
1860             }
1861         }
1862     }
1863   else
1864     {
1865       for(int i=startCellId;i<nbOfCells;i++)
1866         {
1867           if(!isFetched[i])
1868             {
1869               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1870               std::vector<int> v,v2;
1871               if(connOfNode!=connPtr+connIPtr[i+1])
1872                 {
1873                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1874                   connOfNode++;
1875                 }
1876               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1877                 if(*connOfNode>=0)
1878                   {
1879                     v=v2;
1880                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1881                     v2.resize(std::distance(v2.begin(),it));
1882                   }
1883               if(v2.size()>1)
1884                 {
1885                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1886                     {
1887                       int pos=commonCellsI->back();
1888                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1889                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1890                         isFetched[*it]=true;
1891                     }
1892                 }
1893             }
1894         }
1895     }
1896   commonCellsArr=commonCells.retn();
1897   commonCellsIArr=commonCellsI.retn();
1898 }
1899
1900 /*!
1901  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1902  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1903  * than \a other->getNumberOfCells() in the returned array means that there is no
1904  * corresponding cell in \a this mesh.
1905  * It is expected that \a this and \a other meshes share the same node coordinates
1906  * array, if it is not so an exception is thrown. 
1907  *  \param [in] other - the mesh to compare with.
1908  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1909  *         valid values [0,1,2], see zipConnectivityTraducer().
1910  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1911  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1912  *         values. The caller is to delete this array using
1913  *         decrRef() as it is no more needed.
1914  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1915  *         mesh.
1916  *
1917  *  \if ENABLE_EXAMPLES
1918  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1919  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1920  *  \endif
1921  *  \sa checkDeepEquivalOnSameNodesWith()
1922  *  \sa checkGeoEquivalWith()
1923  */
1924 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1925 {
1926   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1927   int nbOfCells=getNumberOfCells();
1928   static const int possibleCompType[]={0,1,2};
1929   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1930     {
1931       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1932       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1933       oss << " !";
1934       throw INTERP_KERNEL::Exception(oss.str().c_str());
1935     }
1936   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1937   arr=o2n->substr(nbOfCells);
1938   arr->setName(other->getName());
1939   int tmp;
1940   if(other->getNumberOfCells()==0)
1941     return true;
1942   return arr->getMaxValue(tmp)<nbOfCells;
1943 }
1944
1945 /*!
1946  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1947  * This method tries to determine if \b other is fully included in \b this.
1948  * The main difference is that this method is not expected to throw exception.
1949  * This method has two outputs :
1950  *
1951  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1952  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1953  */
1954 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1955 {
1956   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1957   DataArrayInt *commonCells=0,*commonCellsI=0;
1958   int thisNbCells=getNumberOfCells();
1959   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1961   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1962   int otherNbCells=other->getNumberOfCells();
1963   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1964   arr2->alloc(otherNbCells,1);
1965   arr2->fillWithZero();
1966   int *arr2Ptr=arr2->getPointer();
1967   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1968   for(int i=0;i<nbOfCommon;i++)
1969     {
1970       int start=commonCellsPtr[commonCellsIPtr[i]];
1971       if(start<thisNbCells)
1972         {
1973           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1974             {
1975               int sig=commonCellsPtr[j]>0?1:-1;
1976               int val=std::abs(commonCellsPtr[j])-1;
1977               if(val>=thisNbCells)
1978                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1979             }
1980         }
1981     }
1982   arr2->setName(other->getName());
1983   if(arr2->presenceOfValue(0))
1984     return false;
1985   arr=arr2.retn();
1986   return true;
1987 }
1988
1989 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1990 {
1991   if(!other)
1992     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1993   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1994   if(!otherC)
1995     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1996   std::vector<const MEDCouplingUMesh *> ms(2);
1997   ms[0]=this;
1998   ms[1]=otherC;
1999   return MergeUMeshesOnSameCoords(ms);
2000 }
2001
2002 /*!
2003  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2004  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2005  * cellIds is not given explicitely but by a range python like.
2006  * 
2007  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2008  * \return a newly allocated
2009  * 
2010  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2011  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2012  */
2013 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2014 {
2015   if(getMeshDimension()!=-1)
2016     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2017   else
2018     {
2019       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2020       if(newNbOfCells!=1)
2021         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2022       if(start!=0)
2023         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2024       incrRef();
2025       return const_cast<MEDCouplingUMesh *>(this);
2026     }
2027 }
2028
2029 /*!
2030  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2031  * The result mesh shares or not the node coordinates array with \a this mesh depending
2032  * on \a keepCoords parameter.
2033  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2034  *           to write this mesh to the MED file, its cells must be sorted using
2035  *           sortCellsInMEDFileFrmt().
2036  *  \param [in] begin - an array of cell ids to include to the new mesh.
2037  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2038  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2039  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2040  *         by calling zipCoords().
2041  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2042  *         to delete this mesh using decrRef() as it is no more needed. 
2043  *  \throw If the coordinates array is not set.
2044  *  \throw If the nodal connectivity of cells is not defined.
2045  *  \throw If any cell id in the array \a begin is not valid.
2046  *
2047  *  \if ENABLE_EXAMPLES
2048  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2049  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2050  *  \endif
2051  */
2052 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2053 {
2054   if(getMeshDimension()!=-1)
2055     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2056   else
2057     {
2058       if(end-begin!=1)
2059         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2060       if(begin[0]!=0)
2061         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2062       incrRef();
2063       return const_cast<MEDCouplingUMesh *>(this);
2064     }
2065 }
2066
2067 /*!
2068  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2069  *
2070  * 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.
2071  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2072  * The number of cells of \b this will remain the same with this method.
2073  *
2074  * \param [in] begin begin of cell ids (included) of cells in this to assign
2075  * \param [in] end end of cell ids (excluded) of cells in this to assign
2076  * \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 ).
2077  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2078  */
2079 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2080 {
2081   checkConnectivityFullyDefined();
2082   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2083   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2084     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2085   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2086     {
2087       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2088       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2089       throw INTERP_KERNEL::Exception(oss.str().c_str());
2090     }
2091   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2092   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2093     {
2094       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2095       throw INTERP_KERNEL::Exception(oss.str().c_str());
2096     }
2097   int nbOfCells=getNumberOfCells();
2098   bool easyAssign=true;
2099   const int *connI=_nodal_connec_index->getConstPointer();
2100   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2101   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2102     {
2103       if(*it>=0 && *it<nbOfCells)
2104         {
2105           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2106         }
2107       else
2108         {
2109           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2110           throw INTERP_KERNEL::Exception(oss.str().c_str());
2111         }
2112     }
2113   if(easyAssign)
2114     {
2115       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2116       computeTypes();
2117     }
2118   else
2119     {
2120       DataArrayInt *arrOut=0,*arrIOut=0;
2121       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2122                                                arrOut,arrIOut);
2123       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2124       setConnectivity(arrOut,arrIOut,true);
2125     }
2126 }
2127
2128 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2129 {
2130   checkConnectivityFullyDefined();
2131   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2132   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2133     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2134   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2135     {
2136       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2137       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2138       throw INTERP_KERNEL::Exception(oss.str().c_str());
2139     }
2140   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2141   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2142     {
2143       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2144       throw INTERP_KERNEL::Exception(oss.str().c_str());
2145     }
2146   int nbOfCells=getNumberOfCells();
2147   bool easyAssign=true;
2148   const int *connI=_nodal_connec_index->getConstPointer();
2149   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2150   int it=start;
2151   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2152     {
2153       if(it>=0 && it<nbOfCells)
2154         {
2155           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2156         }
2157       else
2158         {
2159           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2160           throw INTERP_KERNEL::Exception(oss.str().c_str());
2161         }
2162     }
2163   if(easyAssign)
2164     {
2165       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2166       computeTypes();
2167     }
2168   else
2169     {
2170       DataArrayInt *arrOut=0,*arrIOut=0;
2171       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2172                                                 arrOut,arrIOut);
2173       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2174       setConnectivity(arrOut,arrIOut,true);
2175     }
2176 }                      
2177
2178 /*!
2179  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2180  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2181  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2182  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2183  *
2184  * \param [in] begin input start of array of node ids.
2185  * \param [in] end input end of array of node ids.
2186  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2187  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2188  */
2189 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2190 {
2191   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2192   checkConnectivityFullyDefined();
2193   int tmp=-1;
2194   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2195   std::vector<bool> fastFinder(sz,false);
2196   for(const int *work=begin;work!=end;work++)
2197     if(*work>=0 && *work<sz)
2198       fastFinder[*work]=true;
2199   int nbOfCells=getNumberOfCells();
2200   const int *conn=getNodalConnectivity()->getConstPointer();
2201   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2202   for(int i=0;i<nbOfCells;i++)
2203     {
2204       int ref=0,nbOfHit=0;
2205       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2206         if(*work2>=0)
2207           {
2208             ref++;
2209             if(fastFinder[*work2])
2210               nbOfHit++;
2211           }
2212       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2213         cellIdsKept->pushBackSilent(i);
2214     }
2215   cellIdsKeptArr=cellIdsKept.retn();
2216 }
2217
2218 /*!
2219  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2220  * this->getMeshDimension(), that bound some cells of \a this mesh.
2221  * The cells of lower dimension to include to the result mesh are selected basing on
2222  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2223  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2224  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2225  * created mesh shares the node coordinates array with \a this mesh. 
2226  *  \param [in] begin - the array of node ids.
2227  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2228  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2229  *         array \a begin are added, else cells whose any node is in the
2230  *         array \a begin are added.
2231  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2232  *         to delete this mesh using decrRef() as it is no more needed. 
2233  *  \throw If the coordinates array is not set.
2234  *  \throw If the nodal connectivity of cells is not defined.
2235  *  \throw If any node id in \a begin is not valid.
2236  *
2237  *  \if ENABLE_EXAMPLES
2238  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2239  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2240  *  \endif
2241  */
2242 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2243 {
2244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2245   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2246   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2247   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2248   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2249 }
2250
2251 /*!
2252  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2253  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2254  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2255  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2256  *         by calling zipCoords().
2257  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2258  *         to delete this mesh using decrRef() as it is no more needed. 
2259  *  \throw If the coordinates array is not set.
2260  *  \throw If the nodal connectivity of cells is not defined.
2261  *
2262  *  \if ENABLE_EXAMPLES
2263  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2264  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2265  *  \endif
2266  */
2267 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2268 {
2269   DataArrayInt *desc=DataArrayInt::New();
2270   DataArrayInt *descIndx=DataArrayInt::New();
2271   DataArrayInt *revDesc=DataArrayInt::New();
2272   DataArrayInt *revDescIndx=DataArrayInt::New();
2273   //
2274   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2275   revDesc->decrRef();
2276   desc->decrRef();
2277   descIndx->decrRef();
2278   int nbOfCells=meshDM1->getNumberOfCells();
2279   const int *revDescIndxC=revDescIndx->getConstPointer();
2280   std::vector<int> boundaryCells;
2281   for(int i=0;i<nbOfCells;i++)
2282     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2283       boundaryCells.push_back(i);
2284   revDescIndx->decrRef();
2285   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2286   return ret;
2287 }
2288
2289 /*!
2290  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2291  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2292  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2293  */
2294 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2295 {
2296   checkFullyDefined();
2297   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2300   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2301   //
2302   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2303   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2304   //
2305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2307   const int *revDescPtr=revDesc->getConstPointer();
2308   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2309   int nbOfCells=getNumberOfCells();
2310   std::vector<bool> ret1(nbOfCells,false);
2311   int sz=0;
2312   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2313     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2314       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2315   //
2316   DataArrayInt *ret2=DataArrayInt::New();
2317   ret2->alloc(sz,1);
2318   int *ret2Ptr=ret2->getPointer();
2319   sz=0;
2320   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2321     if(*it)
2322       *ret2Ptr++=sz;
2323   ret2->setName("BoundaryCells");
2324   return ret2;
2325 }
2326
2327 /*!
2328  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2329  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2330  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2331  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2332  *
2333  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2334  * 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
2335  * equals a cell in \b otherDimM1OnSameCoords.
2336  *
2337  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2338  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2339  *
2340  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2341  * \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
2342  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2343  */
2344 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2345 {
2346   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2347     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2348   checkConnectivityFullyDefined();
2349   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2350   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2351     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2352   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2353   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2354   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2356   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2357   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2358   DataArrayInt *idsOtherInConsti=0;
2359   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2361   if(!b)
2362     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2363   std::set<int> s1;
2364   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2365     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2367   s1arr_renum1->sort();
2368   cellIdsRk0=s0arr.retn();
2369   //cellIdsRk1=s_renum1.retn();
2370   cellIdsRk1=s1arr_renum1.retn();
2371 }
2372
2373 /*!
2374  * 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
2375  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2376  * 
2377  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2378  */
2379 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2380 {
2381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2382   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2384   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2385   //
2386   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2387   revDesc=0; desc=0; descIndx=0;
2388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2390   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2391 }
2392
2393 /*!
2394  * Finds nodes lying on the boundary of \a this mesh.
2395  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2396  *          nodes. The caller is to delete this array using decrRef() as it is no
2397  *          more needed.
2398  *  \throw If the coordinates array is not set.
2399  *  \throw If the nodal connectivity of cells is node defined.
2400  *
2401  *  \if ENABLE_EXAMPLES
2402  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2403  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2404  *  \endif
2405  */
2406 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2407 {
2408   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2409   return skin->computeFetchedNodeIds();
2410 }
2411
2412 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2413 {
2414   incrRef();
2415   return const_cast<MEDCouplingUMesh *>(this);
2416 }
2417
2418 /*!
2419  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2420  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2421  * 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.
2422  * 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.
2423  * 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.
2424  *
2425  * \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
2426  *             parameter is altered during the call.
2427  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2428  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2429  * \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.
2430  *
2431  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2432  */
2433 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2434                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2435 {
2436   typedef MEDCouplingAutoRefCountObjectPtr<DataArrayInt> DAInt;
2437
2438   checkFullyDefined();
2439   otherDimM1OnSameCoords.checkFullyDefined();
2440   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2441     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2442   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2443     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2444   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2445   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2446   DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2447   DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2448   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2449   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2450   DAInt s1=m0Part->computeFetchedNodeIds();
2451   DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2452   DAInt s3=s2->buildSubstraction(s1);
2453   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2454   //
2455   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2456   int nCells2 = m0Part2->getNumberOfCells();
2457   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2458   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2459   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2460   DataArrayInt *tmp00=0,*tmp11=0;
2461   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2462   DAInt neighInit00(tmp00);
2463   DAInt neighIInit00(tmp11);
2464   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2465   DataArrayInt *idsTmp=0;
2466   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2467   DAInt ids(idsTmp);
2468   if(!b)
2469     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2470   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2471   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2472   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2473   DataArrayInt *tmp0=0,*tmp1=0;
2474   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2475   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2476   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2477   DAInt neigh00(tmp0);
2478   DAInt neighI00(tmp1);
2479
2480   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2481   int seed = 0, nIter = 0;
2482   int nIterMax = nCells2+1; // Safety net for the loop
2483   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2484   hitCells->fillWithValue(-1);
2485   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2486   cellsToModifyConn0_torenum->alloc(0,1);
2487   while (nIter < nIterMax)
2488     {
2489       DAInt t = hitCells->getIdsEqual(-1);
2490       if (!t->getNumberOfTuples())
2491         break;
2492       // Connex zone without the crack (to compute the next seed really)
2493       int dnu;
2494       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2495       int cnt = 0;
2496       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2497         hitCells->setIJ(*ptr,0,1);
2498       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2499       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2500       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2501       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2502       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2503       DAInt nonHitCells = hitCells->getIdsEqual(-1);
2504       DAInt intersec = nonHitCells->buildIntersection(comple);
2505       if (intersec->getNumberOfTuples())
2506         { seed = intersec->getIJ(0,0); }
2507       else
2508         { break; }
2509       nIter++;
2510     }
2511   if (nIter >= nIterMax)
2512     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2513
2514   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2515   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2516   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2517   //
2518   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2519   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2520   nodeIdsToDuplicate=s3.retn();
2521 }
2522
2523 /*!
2524  * This method operates a modification of the connectivity and coords in \b this.
2525  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2526  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2527  * 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
2528  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2529  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2530  * 
2531  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2532  * 
2533  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2534  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2535  */
2536 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2537 {
2538   int nbOfNodes=getNumberOfNodes();
2539   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2540   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2541 }
2542
2543 /*!
2544  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2545  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2546  *
2547  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2548  *
2549  * \sa renumberNodesInConn
2550  */
2551 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2552 {
2553   checkConnectivityFullyDefined();
2554   int *conn(getNodalConnectivity()->getPointer());
2555   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2556   int nbOfCells(getNumberOfCells());
2557   for(int i=0;i<nbOfCells;i++)
2558     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2559       {
2560         int& node=conn[iconn];
2561         if(node>=0)//avoid polyhedron separator
2562           {
2563             node+=offset;
2564           }
2565       }
2566   _nodal_connec->declareAsNew();
2567   updateTime();
2568 }
2569
2570 /*!
2571  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2572  *  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
2573  *  of a big mesh.
2574  */
2575 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2576 {
2577   checkConnectivityFullyDefined();
2578   int *conn(getNodalConnectivity()->getPointer());
2579   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2580   int nbOfCells(getNumberOfCells());
2581   for(int i=0;i<nbOfCells;i++)
2582     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2583       {
2584         int& node=conn[iconn];
2585         if(node>=0)//avoid polyhedron separator
2586           {
2587             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2588             if(it!=newNodeNumbersO2N.end())
2589               {
2590                 node=(*it).second;
2591               }
2592             else
2593               {
2594                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2595                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2596               }
2597           }
2598       }
2599   _nodal_connec->declareAsNew();
2600   updateTime();
2601 }
2602
2603 /*!
2604  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2605  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2606  * This method is a generalization of shiftNodeNumbersInConn().
2607  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2608  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2609  *         this->getNumberOfNodes(), in "Old to New" mode. 
2610  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2611  *  \throw If the nodal connectivity of cells is not defined.
2612  *
2613  *  \if ENABLE_EXAMPLES
2614  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2615  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2616  *  \endif
2617  */
2618 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2619 {
2620   checkConnectivityFullyDefined();
2621   int *conn=getNodalConnectivity()->getPointer();
2622   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2623   int nbOfCells(getNumberOfCells());
2624   for(int i=0;i<nbOfCells;i++)
2625     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2626       {
2627         int& node=conn[iconn];
2628         if(node>=0)//avoid polyhedron separator
2629           {
2630             node=newNodeNumbersO2N[node];
2631           }
2632       }
2633   _nodal_connec->declareAsNew();
2634   updateTime();
2635 }
2636
2637 /*!
2638  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2639  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2640  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2641  * 
2642  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2643  */
2644 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2645 {
2646   checkConnectivityFullyDefined();
2647   int *conn=getNodalConnectivity()->getPointer();
2648   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2649   int nbOfCells=getNumberOfCells();
2650   for(int i=0;i<nbOfCells;i++)
2651     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2652       {
2653         int& node=conn[iconn];
2654         if(node>=0)//avoid polyhedron separator
2655           {
2656             node+=delta;
2657           }
2658       }
2659   _nodal_connec->declareAsNew();
2660   updateTime();
2661 }
2662
2663 /*!
2664  * This method operates a modification of the connectivity in \b this.
2665  * 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.
2666  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2667  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2668  * 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
2669  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2670  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2671  * 
2672  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2673  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2674  * 
2675  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2676  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2677  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2678  */
2679 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2680 {
2681   checkConnectivityFullyDefined();
2682   std::map<int,int> m;
2683   int val=offset;
2684   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2685     m[*work]=val;
2686   int *conn=getNodalConnectivity()->getPointer();
2687   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2688   int nbOfCells=getNumberOfCells();
2689   for(int i=0;i<nbOfCells;i++)
2690     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2691       {
2692         int& node=conn[iconn];
2693         if(node>=0)//avoid polyhedron separator
2694           {
2695             std::map<int,int>::iterator it=m.find(node);
2696             if(it!=m.end())
2697               node=(*it).second;
2698           }
2699       }
2700   updateTime();
2701 }
2702
2703 /*!
2704  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2705  *
2706  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2707  * After the call of this method the number of cells remains the same as before.
2708  *
2709  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2710  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2711  * be strictly in [0;this->getNumberOfCells()).
2712  *
2713  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2714  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2715  * should be contained in[0;this->getNumberOfCells()).
2716  * 
2717  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2718  */
2719 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2720 {
2721   checkConnectivityFullyDefined();
2722   int nbCells=getNumberOfCells();
2723   const int *array=old2NewBg;
2724   if(check)
2725     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2726   //
2727   const int *conn=_nodal_connec->getConstPointer();
2728   const int *connI=_nodal_connec_index->getConstPointer();
2729   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2730   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2731   const int *n2oPtr=n2o->begin();
2732   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2733   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2734   newConn->copyStringInfoFrom(*_nodal_connec);
2735   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2736   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2737   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2738   //
2739   int *newC=newConn->getPointer();
2740   int *newCI=newConnI->getPointer();
2741   int loc=0;
2742   newCI[0]=loc;
2743   for(int i=0;i<nbCells;i++)
2744     {
2745       int pos=n2oPtr[i];
2746       int nbOfElts=connI[pos+1]-connI[pos];
2747       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2748       loc+=nbOfElts;
2749       newCI[i+1]=loc;
2750     }
2751   //
2752   setConnectivity(newConn,newConnI);
2753   if(check)
2754     free(const_cast<int *>(array));
2755 }
2756
2757 /*!
2758  * Finds cells whose bounding boxes intersect a given bounding box.
2759  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2760  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2761  *         zMax (if in 3D). 
2762  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2763  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2764  *         extent of the bounding box of cell to produce an addition to this bounding box.
2765  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2766  *         cells. The caller is to delete this array using decrRef() as it is no more
2767  *         needed. 
2768  *  \throw If the coordinates array is not set.
2769  *  \throw If the nodal connectivity of cells is not defined.
2770  *
2771  *  \if ENABLE_EXAMPLES
2772  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2773  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2774  *  \endif
2775  */
2776 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2777 {
2778   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2779   if(getMeshDimension()==-1)
2780     {
2781       elems->pushBackSilent(0);
2782       return elems.retn();
2783     }
2784   int dim=getSpaceDimension();
2785   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2786   const int* conn      = getNodalConnectivity()->getConstPointer();
2787   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2788   const double* coords = getCoords()->getConstPointer();
2789   int nbOfCells=getNumberOfCells();
2790   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2791     {
2792       for (int i=0; i<dim; i++)
2793         {
2794           elem_bb[i*2]=std::numeric_limits<double>::max();
2795           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2796         }
2797
2798       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2799         {
2800           int node= conn[inode];
2801           if(node>=0)//avoid polyhedron separator
2802             {
2803               for (int idim=0; idim<dim; idim++)
2804                 {
2805                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2806                     {
2807                       elem_bb[idim*2] = coords[node*dim+idim] ;
2808                     }
2809                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2810                     {
2811                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2812                     }
2813                 }
2814             }
2815         }
2816       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2817         elems->pushBackSilent(ielem);
2818     }
2819   return elems.retn();
2820 }
2821
2822 /*!
2823  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2824  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2825  * added in 'elems' parameter.
2826  */
2827 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2828 {
2829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2830   if(getMeshDimension()==-1)
2831     {
2832       elems->pushBackSilent(0);
2833       return elems.retn();
2834     }
2835   int dim=getSpaceDimension();
2836   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2837   const int* conn      = getNodalConnectivity()->getConstPointer();
2838   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2839   const double* coords = getCoords()->getConstPointer();
2840   int nbOfCells=getNumberOfCells();
2841   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2842     {
2843       for (int i=0; i<dim; i++)
2844         {
2845           elem_bb[i*2]=std::numeric_limits<double>::max();
2846           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2847         }
2848
2849       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2850         {
2851           int node= conn[inode];
2852           if(node>=0)//avoid polyhedron separator
2853             {
2854               for (int idim=0; idim<dim; idim++)
2855                 {
2856                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2857                     {
2858                       elem_bb[idim*2] = coords[node*dim+idim] ;
2859                     }
2860                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2861                     {
2862                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2863                     }
2864                 }
2865             }
2866         }
2867       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2868         elems->pushBackSilent(ielem);
2869     }
2870   return elems.retn();
2871 }
2872
2873 /*!
2874  * Returns a type of a cell by its id.
2875  *  \param [in] cellId - the id of the cell of interest.
2876  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2877  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2878  */
2879 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2880 {
2881   const int *ptI=_nodal_connec_index->getConstPointer();
2882   const int *pt=_nodal_connec->getConstPointer();
2883   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2884     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2885   else
2886     {
2887       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2888       throw INTERP_KERNEL::Exception(oss.str().c_str());
2889     }
2890 }
2891
2892 /*!
2893  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2894  * This method does not throw exception if geometric type \a type is not in \a this.
2895  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2896  * The coordinates array is not considered here.
2897  *
2898  * \param [in] type the geometric type
2899  * \return cell ids in this having geometric type \a type.
2900  */
2901 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2902 {
2903
2904   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2905   ret->alloc(0,1);
2906   checkConnectivityFullyDefined();
2907   int nbCells=getNumberOfCells();
2908   int mdim=getMeshDimension();
2909   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2910   if(mdim!=(int)cm.getDimension())
2911     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2912   const int *ptI=_nodal_connec_index->getConstPointer();
2913   const int *pt=_nodal_connec->getConstPointer();
2914   for(int i=0;i<nbCells;i++)
2915     {
2916       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2917         ret->pushBackSilent(i);
2918     }
2919   return ret.retn();
2920 }
2921
2922 /*!
2923  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2924  */
2925 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2926 {
2927   const int *ptI=_nodal_connec_index->getConstPointer();
2928   const int *pt=_nodal_connec->getConstPointer();
2929   int nbOfCells=getNumberOfCells();
2930   int ret=0;
2931   for(int i=0;i<nbOfCells;i++)
2932     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2933       ret++;
2934   return ret;
2935 }
2936
2937 /*!
2938  * Returns the nodal connectivity of a given cell.
2939  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2940  * all returned node ids can be used in getCoordinatesOfNode().
2941  *  \param [in] cellId - an id of the cell of interest.
2942  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2943  *         cleared before the appending.
2944  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2945  */
2946 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2947 {
2948   const int *ptI=_nodal_connec_index->getConstPointer();
2949   const int *pt=_nodal_connec->getConstPointer();
2950   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2951     if(*w>=0)
2952       conn.push_back(*w);
2953 }
2954
2955 std::string MEDCouplingUMesh::simpleRepr() const
2956 {
2957   static const char msg0[]="No coordinates specified !";
2958   std::ostringstream ret;
2959   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2960   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2961   int tmpp1,tmpp2;
2962   double tt=getTime(tmpp1,tmpp2);
2963   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2964   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2965   if(_mesh_dim>=-1)
2966     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2967   else
2968     { ret << " Mesh dimension has not been set or is invalid !"; }
2969   if(_coords!=0)
2970     {
2971       const int spaceDim=getSpaceDimension();
2972       ret << spaceDim << "\nInfo attached on space dimension : ";
2973       for(int i=0;i<spaceDim;i++)
2974         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2975       ret << "\n";
2976     }
2977   else
2978     ret << msg0 << "\n";
2979   ret << "Number of nodes : ";
2980   if(_coords!=0)
2981     ret << getNumberOfNodes() << "\n";
2982   else
2983     ret << msg0 << "\n";
2984   ret << "Number of cells : ";
2985   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2986     ret << getNumberOfCells() << "\n";
2987   else
2988     ret << "No connectivity specified !" << "\n";
2989   ret << "Cell types present : ";
2990   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2991     {
2992       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2993       ret << cm.getRepr() << " ";
2994     }
2995   ret << "\n";
2996   return ret.str();
2997 }
2998
2999 std::string MEDCouplingUMesh::advancedRepr() const
3000 {
3001   std::ostringstream ret;
3002   ret << simpleRepr();
3003   ret << "\nCoordinates array : \n___________________\n\n";
3004   if(_coords)
3005     _coords->reprWithoutNameStream(ret);
3006   else
3007     ret << "No array set !\n";
3008   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3009   reprConnectivityOfThisLL(ret);
3010   return ret.str();
3011 }
3012
3013 /*!
3014  * This method returns a C++ code that is a dump of \a this.
3015  * This method will throw if this is not fully defined.
3016  */
3017 std::string MEDCouplingUMesh::cppRepr() const
3018 {
3019   static const char coordsName[]="coords";
3020   static const char connName[]="conn";
3021   static const char connIName[]="connI";
3022   checkFullyDefined();
3023   std::ostringstream ret; ret << "// coordinates" << std::endl;
3024   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3025   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3026   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3027   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3028   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3029   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3030   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3031   return ret.str();
3032 }
3033
3034 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3035 {
3036   std::ostringstream ret;
3037   reprConnectivityOfThisLL(ret);
3038   return ret.str();
3039 }
3040
3041 /*!
3042  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3043  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3044  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3045  * some algos).
3046  * 
3047  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3048  * 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
3049  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3050  */
3051 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3052 {
3053   int mdim=getMeshDimension();
3054   if(mdim<0)
3055     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3056   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3057   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3058   bool needToCpyCT=true;
3059   if(!_nodal_connec)
3060     {
3061       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3062       needToCpyCT=false;
3063     }
3064   else
3065     {
3066       tmp1=_nodal_connec;
3067       tmp1->incrRef();
3068     }
3069   if(!_nodal_connec_index)
3070     {
3071       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3072       needToCpyCT=false;
3073     }
3074   else
3075     {
3076       tmp2=_nodal_connec_index;
3077       tmp2->incrRef();
3078     }
3079   ret->setConnectivity(tmp1,tmp2,false);
3080   if(needToCpyCT)
3081     ret->_types=_types;
3082   if(!_coords)
3083     {
3084       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3085       ret->setCoords(coords);
3086     }
3087   else
3088     ret->setCoords(_coords);
3089   return ret.retn();
3090 }
3091
3092 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3093 {
3094   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3095     {
3096       int nbOfCells=getNumberOfCells();
3097       const int *c=_nodal_connec->getConstPointer();
3098       const int *ci=_nodal_connec_index->getConstPointer();
3099       for(int i=0;i<nbOfCells;i++)
3100         {
3101           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3102           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3103           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3104           stream << "\n";
3105         }
3106     }
3107   else
3108     stream << "Connectivity not defined !\n";
3109 }
3110
3111 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3112 {
3113   const int *ptI=_nodal_connec_index->getConstPointer();
3114   const int *pt=_nodal_connec->getConstPointer();
3115   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3116     return ptI[cellId+1]-ptI[cellId]-1;
3117   else
3118     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3119 }
3120
3121 /*!
3122  * Returns types of cells of the specified part of \a this mesh.
3123  * This method avoids computing sub-mesh explicitely to get its types.
3124  *  \param [in] begin - an array of cell ids of interest.
3125  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3126  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3127  *         describing the cell types. 
3128  *  \throw If the coordinates array is not set.
3129  *  \throw If the nodal connectivity of cells is not defined.
3130  *  \sa getAllGeoTypes()
3131  */
3132 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3133 {
3134   checkFullyDefined();
3135   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3136   const int *conn=_nodal_connec->getConstPointer();
3137   const int *connIndex=_nodal_connec_index->getConstPointer();
3138   for(const int *w=begin;w!=end;w++)
3139     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3140   return ret;
3141 }
3142
3143 /*!
3144  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3145  * a set of types of cells constituting \a this mesh. 
3146  * This method is for advanced users having prepared their connectivity before. For
3147  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3148  *  \param [in] conn - the nodal connectivity array. 
3149  *  \param [in] connIndex - the nodal connectivity index array.
3150  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3151  *         mesh is updated.
3152  */
3153 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3154 {
3155   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3156   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3157   if(isComputingTypes)
3158     computeTypes();
3159   declareAsNew();
3160 }
3161
3162 /*!
3163  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3164  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3165  */
3166 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3167     _nodal_connec(0),_nodal_connec_index(0),
3168     _types(other._types)
3169 {
3170   if(other._nodal_connec)
3171     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3172   if(other._nodal_connec_index)
3173     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3174 }
3175
3176 MEDCouplingUMesh::~MEDCouplingUMesh()
3177 {
3178   if(_nodal_connec)
3179     _nodal_connec->decrRef();
3180   if(_nodal_connec_index)
3181     _nodal_connec_index->decrRef();
3182 }
3183
3184 /*!
3185  * Recomputes a set of cell types of \a this mesh. For more info see
3186  * \ref MEDCouplingUMeshNodalConnectivity.
3187  */
3188 void MEDCouplingUMesh::computeTypes()
3189 {
3190   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3191 }
3192
3193 /*!
3194  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3195  */
3196 void MEDCouplingUMesh::checkFullyDefined() const
3197 {
3198   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3199     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3200 }
3201
3202 /*!
3203  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3204  */
3205 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3206 {
3207   if(!_nodal_connec_index || !_nodal_connec)
3208     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3209 }
3210
3211 /*!
3212  * Returns a number of cells constituting \a this mesh. 
3213  *  \return int - the number of cells in \a this mesh.
3214  *  \throw If the nodal connectivity of cells is not defined.
3215  */
3216 int MEDCouplingUMesh::getNumberOfCells() const
3217
3218   if(_nodal_connec_index)
3219     return _nodal_connec_index->getNumberOfTuples()-1;
3220   else
3221     if(_mesh_dim==-1)
3222       return 1;
3223     else
3224       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3225 }
3226
3227 /*!
3228  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3229  * mesh. For more info see \ref MEDCouplingMeshesPage.
3230  *  \return int - the dimension of \a this mesh.
3231  *  \throw If the mesh dimension is not defined using setMeshDimension().
3232  */
3233 int MEDCouplingUMesh::getMeshDimension() const
3234 {
3235   if(_mesh_dim<-1)
3236     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3237   return _mesh_dim;
3238 }
3239
3240 /*!
3241  * Returns a length of the nodal connectivity array.
3242  * This method is for test reason. Normally the integer returned is not useable by
3243  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3244  *  \return int - the length of the nodal connectivity array.
3245  */
3246 int MEDCouplingUMesh::getMeshLength() const
3247 {
3248   return _nodal_connec->getNbOfElems();
3249 }
3250
3251 /*!
3252  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3253  */
3254 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3255 {
3256   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3257   tinyInfo.push_back(getMeshDimension());
3258   tinyInfo.push_back(getNumberOfCells());
3259   if(_nodal_connec)
3260     tinyInfo.push_back(getMeshLength());
3261   else
3262     tinyInfo.push_back(-1);
3263 }
3264
3265 /*!
3266  * First step of unserialization process.
3267  */
3268 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3269 {
3270   return tinyInfo[6]<=0;
3271 }
3272
3273 /*!
3274  * Second step of serialization process.
3275  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3276  */
3277 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3278 {
3279   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3280   if(tinyInfo[5]!=-1)
3281     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3282 }
3283
3284 /*!
3285  * Third and final step of serialization process.
3286  */
3287 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3288 {
3289   MEDCouplingPointSet::serialize(a1,a2);
3290   if(getMeshDimension()>-1)
3291     {
3292       a1=DataArrayInt::New();
3293       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3294       int *ptA1=a1->getPointer();
3295       const int *conn=getNodalConnectivity()->getConstPointer();
3296       const int *index=getNodalConnectivityIndex()->getConstPointer();
3297       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3298       std::copy(conn,conn+getMeshLength(),ptA1);
3299     }
3300   else
3301     a1=0;
3302 }
3303
3304 /*!
3305  * Second and final unserialization process.
3306  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3307  */
3308 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3309 {
3310   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3311   setMeshDimension(tinyInfo[5]);
3312   if(tinyInfo[7]!=-1)
3313     {
3314       // Connectivity
3315       const int *recvBuffer=a1->getConstPointer();
3316       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3317       myConnecIndex->alloc(tinyInfo[6]+1,1);
3318       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3319       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3320       myConnec->alloc(tinyInfo[7],1);
3321       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3322       setConnectivity(myConnec, myConnecIndex);
3323     }
3324 }
3325
3326 /*!
3327  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3328  * CellIds are given using range specified by a start an end and step.
3329  */
3330 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3331 {
3332   checkFullyDefined();
3333   int ncell=getNumberOfCells();
3334   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3335   ret->_mesh_dim=_mesh_dim;
3336   ret->setCoords(_coords);
3337   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3339   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3340   int work=start;
3341   const int *conn=_nodal_connec->getConstPointer();
3342   const int *connIndex=_nodal_connec_index->getConstPointer();
3343   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3344     {
3345       if(work>=0 && work<ncell)
3346         {
3347           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3348         }
3349       else
3350         {
3351           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3352           throw INTERP_KERNEL::Exception(oss.str().c_str());
3353         }
3354     }
3355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3356   int *newConnPtr=newConn->getPointer();
3357   std::set<INTERP_KERNEL::NormalizedCellType> types;
3358   work=start;
3359   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3360     {
3361       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3362       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3363     }
3364   ret->setConnectivity(newConn,newConnI,false);
3365   ret->_types=types;
3366   ret->copyTinyInfoFrom(this);
3367   return ret.retn();
3368 }
3369
3370 /*!
3371  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3372  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3373  * The return newly allocated mesh will share the same coordinates as \a this.
3374  */
3375 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3376 {
3377   checkConnectivityFullyDefined();
3378   int ncell=getNumberOfCells();
3379   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3380   ret->_mesh_dim=_mesh_dim;
3381   ret->setCoords(_coords);
3382   std::size_t nbOfElemsRet=std::distance(begin,end);
3383   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3384   connIndexRet[0]=0;
3385   const int *conn=_nodal_connec->getConstPointer();
3386   const int *connIndex=_nodal_connec_index->getConstPointer();
3387   int newNbring=0;
3388   for(const int *work=begin;work!=end;work++,newNbring++)
3389     {
3390       if(*work>=0 && *work<ncell)
3391         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3392       else
3393         {
3394           free(connIndexRet);
3395           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3396           throw INTERP_KERNEL::Exception(oss.str().c_str());
3397         }
3398     }
3399   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3400   int *connRetWork=connRet;
3401   std::set<INTERP_KERNEL::NormalizedCellType> types;
3402   for(const int *work=begin;work!=end;work++)
3403     {
3404       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3405       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3406     }
3407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3408   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3409   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3410   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3411   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3412   ret->_types=types;
3413   ret->copyTinyInfoFrom(this);
3414   return ret.retn();
3415 }
3416
3417 /*!
3418  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3419  * mesh.<br>
3420  * For 1D cells, the returned field contains lengths.<br>
3421  * For 2D cells, the returned field contains areas.<br>
3422  * For 3D cells, the returned field contains volumes.
3423  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3424  *         orientation, i.e. the volume is always positive.
3425  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3426  *         and one time . The caller is to delete this field using decrRef() as it is no
3427  *         more needed.
3428  */
3429 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3430 {
3431   std::string name="MeasureOfMesh_";
3432   name+=getName();
3433   int nbelem=getNumberOfCells();
3434   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3435   field->setName(name);
3436   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3437   array->alloc(nbelem,1);
3438   double *area_vol=array->getPointer();
3439   field->setArray(array) ; array=0;
3440   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3441   field->synchronizeTimeWithMesh();
3442   if(getMeshDimension()!=-1)
3443     {
3444       int ipt;
3445       INTERP_KERNEL::NormalizedCellType type;
3446       int dim_space=getSpaceDimension();
3447       const double *coords=getCoords()->getConstPointer();
3448       const int *connec=getNodalConnectivity()->getConstPointer();
3449       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3450       for(int iel=0;iel<nbelem;iel++)
3451         {
3452           ipt=connec_index[iel];
3453           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3454           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);
3455         }
3456       if(isAbs)
3457         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3458     }
3459   else
3460     {
3461       area_vol[0]=std::numeric_limits<double>::max();
3462     }
3463   return field.retn();
3464 }
3465
3466 /*!
3467  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3468  * mesh.<br>
3469  * For 1D cells, the returned array contains lengths.<br>
3470  * For 2D cells, the returned array contains areas.<br>
3471  * For 3D cells, the returned array contains volumes.
3472  * This method avoids building explicitly a part of \a this mesh to perform the work.
3473  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3474  *         orientation, i.e. the volume is always positive.
3475  *  \param [in] begin - an array of cell ids of interest.
3476  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3477  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3478  *          delete this array using decrRef() as it is no more needed.
3479  * 
3480  *  \if ENABLE_EXAMPLES
3481  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3482  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3483  *  \endif
3484  *  \sa getMeasureField()
3485  */
3486 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3487 {
3488   std::string name="PartMeasureOfMesh_";
3489   name+=getName();
3490   int nbelem=(int)std::distance(begin,end);
3491   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3492   array->setName(name);
3493   array->alloc(nbelem,1);
3494   double *area_vol=array->getPointer();
3495   if(getMeshDimension()!=-1)
3496     {
3497       int ipt;
3498       INTERP_KERNEL::NormalizedCellType type;
3499       int dim_space=getSpaceDimension();
3500       const double *coords=getCoords()->getConstPointer();
3501       const int *connec=getNodalConnectivity()->getConstPointer();
3502       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3503       for(const int *iel=begin;iel!=end;iel++)
3504         {
3505           ipt=connec_index[*iel];
3506           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3507           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3508         }
3509       if(isAbs)
3510         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3511     }
3512   else
3513     {
3514       area_vol[0]=std::numeric_limits<double>::max();
3515     }
3516   return array.retn();
3517 }
3518
3519 /*!
3520  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3521  * \a this one. The returned field contains the dual cell volume for each corresponding
3522  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3523  *  the dual mesh in P1 sens of \a this.<br>
3524  * For 1D cells, the returned field contains lengths.<br>
3525  * For 2D cells, the returned field contains areas.<br>
3526  * For 3D cells, the returned field contains volumes.
3527  * This method is useful to check "P1*" conservative interpolators.
3528  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3529  *         orientation, i.e. the volume is always positive.
3530  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3531  *          nodes and one time. The caller is to delete this array using decrRef() as
3532  *          it is no more needed.
3533  */
3534 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3535 {
3536   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3537   std::string name="MeasureOnNodeOfMesh_";
3538   name+=getName();
3539   int nbNodes=getNumberOfNodes();
3540   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3541   double cst=1./((double)getMeshDimension()+1.);
3542   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3543   array->alloc(nbNodes,1);
3544   double *valsToFill=array->getPointer();
3545   std::fill(valsToFill,valsToFill+nbNodes,0.);
3546   const double *values=tmp->getArray()->getConstPointer();
3547   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3548   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3549   getReverseNodalConnectivity(da,daInd);
3550   const int *daPtr=da->getConstPointer();
3551   const int *daIPtr=daInd->getConstPointer();
3552   for(int i=0;i<nbNodes;i++)
3553     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3554       valsToFill[i]+=cst*values[*cell];
3555   ret->setMesh(this);
3556   ret->setArray(array);
3557   return ret.retn();
3558 }
3559
3560 /*!
3561  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3562  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3563  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3564  * and are normalized.
3565  * <br> \a this can be either 
3566  * - a  2D mesh in 2D or 3D space or 
3567  * - an 1D mesh in 2D space.
3568  * 
3569  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3570  *          cells and one time. The caller is to delete this field using decrRef() as
3571  *          it is no more needed.
3572  *  \throw If the nodal connectivity of cells is not defined.
3573  *  \throw If the coordinates array is not set.
3574  *  \throw If the mesh dimension is not set.
3575  *  \throw If the mesh and space dimension is not as specified above.
3576  */
3577 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3578 {
3579   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3580     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3581   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3582   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3583   int nbOfCells=getNumberOfCells();
3584   int nbComp=getMeshDimension()+1;
3585   array->alloc(nbOfCells,nbComp);
3586   double *vals=array->getPointer();
3587   const int *connI=_nodal_connec_index->getConstPointer();
3588   const int *conn=_nodal_connec->getConstPointer();
3589   const double *coords=_coords->getConstPointer();
3590   if(getMeshDimension()==2)
3591     {
3592       if(getSpaceDimension()==3)
3593         {
3594           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3595           const double *locPtr=loc->getConstPointer();
3596           for(int i=0;i<nbOfCells;i++,vals+=3)
3597             {
3598               int offset=connI[i];
3599               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3600               double n=INTERP_KERNEL::norm<3>(vals);
3601               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3602             }
3603         }
3604       else
3605         {
3606           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3607           const double *isAbsPtr=isAbs->getArray()->begin();
3608           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3609             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3610         }
3611     }
3612   else//meshdimension==1
3613     {
3614       double tmp[2];
3615       for(int i=0;i<nbOfCells;i++)
3616         {
3617           int offset=connI[i];
3618           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3619           double n=INTERP_KERNEL::norm<2>(tmp);
3620           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3621           *vals++=-tmp[1];
3622           *vals++=tmp[0];
3623         }
3624     }
3625   ret->setArray(array);
3626   ret->setMesh(this);
3627   ret->synchronizeTimeWithSupport();
3628   return ret.retn();
3629 }
3630
3631 /*!
3632  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3633  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3634  * and are normalized.
3635  * <br> \a this can be either 
3636  * - a  2D mesh in 2D or 3D space or 
3637  * - an 1D mesh in 2D space.
3638  * 
3639  * This method avoids building explicitly a part of \a this mesh to perform the work.
3640  *  \param [in] begin - an array of cell ids of interest.
3641  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3642  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3643  *          cells and one time. The caller is to delete this field using decrRef() as
3644  *          it is no more needed.
3645  *  \throw If the nodal connectivity of cells is not defined.
3646  *  \throw If the coordinates array is not set.
3647  *  \throw If the mesh dimension is not set.
3648  *  \throw If the mesh and space dimension is not as specified above.
3649  *  \sa buildOrthogonalField()
3650  *
3651  *  \if ENABLE_EXAMPLES
3652  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3653  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3654  *  \endif
3655  */
3656 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3657 {
3658   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3659     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3660   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3661   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3662   std::size_t nbelems=std::distance(begin,end);
3663   int nbComp=getMeshDimension()+1;
3664   array->alloc((int)nbelems,nbComp);
3665   double *vals=array->getPointer();
3666   const int *connI=_nodal_connec_index->getConstPointer();
3667   const int *conn=_nodal_connec->getConstPointer();
3668   const double *coords=_coords->getConstPointer();
3669   if(getMeshDimension()==2)
3670     {
3671       if(getSpaceDimension()==3)
3672         {
3673           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3674           const double *locPtr=loc->getConstPointer();
3675           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3676             {
3677               int offset=connI[*i];
3678               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3679               double n=INTERP_KERNEL::norm<3>(vals);
3680               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3681             }
3682         }
3683       else
3684         {
3685           for(std::size_t i=0;i<nbelems;i++)
3686             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3687         }
3688     }
3689   else//meshdimension==1
3690     {
3691       double tmp[2];
3692       for(const int *i=begin;i!=end;i++)
3693         {
3694           int offset=connI[*i];
3695           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3696           double n=INTERP_KERNEL::norm<2>(tmp);
3697           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3698           *vals++=-tmp[1];
3699           *vals++=tmp[0];
3700         }
3701     }
3702   ret->setArray(array);
3703   ret->setMesh(this);
3704   ret->synchronizeTimeWithSupport();
3705   return ret.retn();
3706 }
3707
3708 /*!
3709  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3710  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3711  * and are \b not normalized.
3712  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3713  *          cells and one time. The caller is to delete this field using decrRef() as
3714  *          it is no more needed.
3715  *  \throw If the nodal connectivity of cells is not defined.
3716  *  \throw If the coordinates array is not set.
3717  *  \throw If \a this->getMeshDimension() != 1.
3718  *  \throw If \a this mesh includes cells of type other than SEG2.
3719  */
3720 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3721 {
3722   if(getMeshDimension()!=1)
3723     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3724   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3725     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3726   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3727   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3728   int nbOfCells=getNumberOfCells();
3729   int spaceDim=getSpaceDimension();
3730   array->alloc(nbOfCells,spaceDim);
3731   double *pt=array->getPointer();
3732   const double *coo=getCoords()->getConstPointer();
3733   std::vector<int> conn;
3734   conn.reserve(2);
3735   for(int i=0;i<nbOfCells;i++)
3736     {
3737       conn.resize(0);
3738       getNodeIdsOfCell(i,conn);
3739       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3740     }
3741   ret->setArray(array);
3742   ret->setMesh(this);
3743   ret->synchronizeTimeWithSupport();
3744   return ret.retn();
3745 }
3746
3747 /*!
3748  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3749  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3750  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3751  * from. If a result face is shared by two 3D cells, then the face in included twice in
3752  * the result mesh.
3753  *  \param [in] origin - 3 components of a point defining location of the plane.
3754  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3755  *         must be greater than 1e-6.
3756  *  \param [in] eps - half-thickness of the plane.
3757  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3758  *         producing correspondent 2D cells. The caller is to delete this array
3759  *         using decrRef() as it is no more needed.
3760  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3761  *         not share the node coordinates array with \a this mesh. The caller is to
3762  *         delete this mesh using decrRef() as it is no more needed.  
3763  *  \throw If the coordinates array is not set.
3764  *  \throw If the nodal connectivity of cells is not defined.
3765  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3766  *  \throw If magnitude of \a vec is less than 1e-6.
3767  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3768  *  \throw If \a this includes quadratic cells.
3769  */
3770 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3771 {
3772   checkFullyDefined();
3773   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3774     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3775   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3776   if(candidates->empty())
3777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3778   std::vector<int> nodes;
3779   DataArrayInt *cellIds1D=0;
3780   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3781   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3782   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3783   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3785   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3786   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3787   revDesc2=0; revDescIndx2=0;
3788   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3789   revDesc1=0; revDescIndx1=0;
3790   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3791   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3792   //
3793   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3794   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3795     cut3DCurve[*it]=-1;
3796   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3797   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3798   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3799                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3800                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3801   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3802   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3803   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3804   if(cellIds2->empty())
3805     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3806   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3807   ret->setCoords(mDesc1->getCoords());
3808   ret->setConnectivity(conn,connI,true);
3809   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3810   return ret.retn();
3811 }
3812
3813 /*!
3814  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3815 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
3816 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3817 the result mesh.
3818  *  \param [in] origin - 3 components of a point defining location of the plane.
3819  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3820  *         must be greater than 1e-6.
3821  *  \param [in] eps - half-thickness of the plane.
3822  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3823  *         producing correspondent segments. The caller is to delete this array
3824  *         using decrRef() as it is no more needed.
3825  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3826  *         mesh in 3D space. This mesh does not share the node coordinates array with
3827  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3828  *         no more needed. 
3829  *  \throw If the coordinates array is not set.
3830  *  \throw If the nodal connectivity of cells is not defined.
3831  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3832  *  \throw If magnitude of \a vec is less than 1e-6.
3833  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3834  *  \throw If \a this includes quadratic cells.
3835  */
3836 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3837 {
3838   checkFullyDefined();
3839   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3840     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3842   if(candidates->empty())
3843     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3844   std::vector<int> nodes;
3845   DataArrayInt *cellIds1D=0;
3846   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3847   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3849   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3851   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3852   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3853   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3854   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3855   //
3856   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3857   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3858     cut3DCurve[*it]=-1;
3859   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3860   int ncellsSub=subMesh->getNumberOfCells();
3861   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3862   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3863                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3864                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3866   conn->alloc(0,1);
3867   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3868   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3869   for(int i=0;i<ncellsSub;i++)
3870     {
3871       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3872         {
3873           if(cut3DSurf[i].first!=-2)
3874             {
3875               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3876               connI->pushBackSilent(conn->getNumberOfTuples());
3877               cellIds2->pushBackSilent(i);
3878             }
3879           else
3880             {
3881               int cellId3DSurf=cut3DSurf[i].second;
3882               int offset=nodalI[cellId3DSurf]+1;
3883               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3884               for(int j=0;j<nbOfEdges;j++)
3885                 {
3886                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3887                   connI->pushBackSilent(conn->getNumberOfTuples());
3888                   cellIds2->pushBackSilent(cellId3DSurf);
3889                 }
3890             }
3891         }
3892     }
3893   if(cellIds2->empty())
3894     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3895   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3896   ret->setCoords(mDesc1->getCoords());
3897   ret->setConnectivity(conn,connI,true);
3898   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3899   return ret.retn();
3900 }
3901
3902 /*!
3903  * Finds cells whose bounding boxes intersect a given plane.
3904  *  \param [in] origin - 3 components of a point defining location of the plane.
3905  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3906  *         must be greater than 1e-6.
3907  *  \param [in] eps - half-thickness of the plane.
3908  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3909  *         cells. The caller is to delete this array using decrRef() as it is no more
3910  *         needed.
3911  *  \throw If the coordinates array is not set.
3912  *  \throw If the nodal connectivity of cells is not defined.
3913  *  \throw If \a this->getSpaceDimension() != 3.
3914  *  \throw If magnitude of \a vec is less than 1e-6.
3915  *  \sa buildSlice3D()
3916  */
3917 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3918 {
3919   checkFullyDefined();
3920   if(getSpaceDimension()!=3)
3921     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3922   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3923   if(normm<1e-6)
3924     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3925   double vec2[3];
3926   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3927   double angle=acos(vec[2]/normm);
3928   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3929   double bbox[6];
3930   if(angle>eps)
3931     {
3932       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3933       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3934       if(normm2/normm>1e-6)
3935         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3936       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3937       mw->setCoords(coo);
3938       mw->getBoundingBox(bbox);
3939       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3940       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3941     }
3942   else
3943     {
3944       getBoundingBox(bbox);
3945       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3946       cellIds=getCellsInBoundingBox(bbox,eps);
3947     }
3948   return cellIds.retn();
3949 }
3950
3951 /*!
3952  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3953  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3954  * No consideration of coordinate is done by this method.
3955  * 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)
3956  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3957  */
3958 bool MEDCouplingUMesh::isContiguous1D() const
3959 {
3960   if(getMeshDimension()!=1)
3961     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3962   int nbCells=getNumberOfCells();
3963   if(nbCells<1)
3964     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3965   const int *connI=_nodal_connec_index->getConstPointer();
3966   const int *conn=_nodal_connec->getConstPointer();
3967   int ref=conn[connI[0]+2];
3968   for(int i=1;i<nbCells;i++)
3969     {
3970       if(conn[connI[i]+1]!=ref)
3971         return false;
3972       ref=conn[connI[i]+2];
3973     }
3974   return true;
3975 }
3976
3977 /*!
3978  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3979  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3980  * \param pt reference point of the line
3981  * \param v normalized director vector of the line
3982  * \param eps max precision before throwing an exception
3983  * \param res output of size this->getNumberOfCells
3984  */
3985 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3986 {
3987   if(getMeshDimension()!=1)
3988     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3989   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3990     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3991   if(getSpaceDimension()!=3)
3992     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3993   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3994   const double *fPtr=f->getArray()->getConstPointer();
3995   double tmp[3];
3996   for(int i=0;i<getNumberOfCells();i++)
3997     {
3998       const double *tmp1=fPtr+3*i;
3999       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4000       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4001       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4002       double n1=INTERP_KERNEL::norm<3>(tmp);
4003       n1/=INTERP_KERNEL::norm<3>(tmp1);
4004       if(n1>eps)
4005         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4006     }
4007   const double *coo=getCoords()->getConstPointer();
4008   for(int i=0;i<getNumberOfNodes();i++)
4009     {
4010       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4011       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4012       res[i]=std::accumulate(tmp,tmp+3,0.);
4013     }
4014 }
4015
4016 /*!
4017  * 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. 
4018  * \a this is expected to be a mesh so that its space dimension is equal to its
4019  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4020  * 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).
4021  *
4022  * 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
4023  * 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).
4024  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4025  *
4026  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4027  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4028  *
4029  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4030  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4031  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4032  * \return the positive value of the distance.
4033  * \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
4034  * dimension - 1.
4035  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4036  */
4037 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4038 {
4039   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4040   if(meshDim!=spaceDim-1)
4041     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4042   if(meshDim!=2 && meshDim!=1)
4043     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4044   checkFullyDefined();
4045   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4046     { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
4047   DataArrayInt *ret1=0;
4048   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4049   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4051   cellId=*ret1Safe->begin();
4052   return *ret0->begin();
4053 }
4054
4055 /*!
4056  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4057  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4058  * 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
4059  * 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).
4060  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4061  * 
4062  * \a this is expected to be a mesh so that its space dimension is equal to its
4063  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4064  * 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).
4065  *
4066  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4067  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4068  *
4069  * \param [in] pts the list of points in which each tuple represents a point
4070  * \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.
4071  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4072  * \throw if number of components of \a pts is not equal to the space dimension.
4073  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4074  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4075  */
4076 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4077 {
4078   if(!pts)
4079     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4080   pts->checkAllocated();
4081   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4082   if(meshDim!=spaceDim-1)
4083     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4084   if(meshDim!=2 && meshDim!=1)
4085     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4086   if(pts->getNumberOfComponents()!=spaceDim)
4087     {
4088       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4089       throw INTERP_KERNEL::Exception(oss.str().c_str());
4090     }
4091   checkFullyDefined();
4092   int nbCells=getNumberOfCells();
4093   if(nbCells==0)
4094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4095   int nbOfPts=pts->getNumberOfTuples();
4096   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4097   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4098   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4099   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4100   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4101   const double *bbox(bboxArr->begin());
4102   switch(spaceDim)
4103   {
4104     case 3:
4105       {
4106         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4107         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4108           {
4109             double x=std::numeric_limits<double>::max();
4110             std::vector<int> elems;
4111             myTree.getMinDistanceOfMax(ptsPtr,x);
4112             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4113             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4114           }
4115         break;
4116       }
4117     case 2:
4118       {
4119         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4120         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4121           {
4122             double x=std::numeric_limits<double>::max();
4123             std::vector<int> elems;
4124             myTree.getMinDistanceOfMax(ptsPtr,x);
4125             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4126             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4127           }
4128         break;
4129       }
4130     default:
4131       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4132   }
4133   cellIds=ret1.retn();
4134   return ret0.retn();
4135 }
4136
4137 /*!
4138  * \param [in] pt the start pointer (included) of the coordinates of the point
4139  * \param [in] cellIdsBg the start pointer (included) of cellIds
4140  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4141  * \param [in] nc nodal connectivity
4142  * \param [in] ncI nodal connectivity index
4143  * \param [in,out] ret0 the min distance between \a this and the external input point
4144  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4145  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4146  */
4147 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)
4148 {
4149   cellId=-1;
4150   ret0=std::numeric_limits<double>::max();
4151   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4152     {
4153       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4154       {
4155         case INTERP_KERNEL::NORM_TRI3:
4156           {
4157             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4158             if(tmp<ret0)
4159               { ret0=tmp; cellId=*zeCell; }
4160             break;
4161           }
4162         case INTERP_KERNEL::NORM_QUAD4:
4163         case INTERP_KERNEL::NORM_POLYGON:
4164           {
4165             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4166             if(tmp<ret0)
4167               { ret0=tmp; cellId=*zeCell; }
4168             break;
4169           }
4170         default:
4171           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4172       }
4173     }
4174 }
4175
4176 /*!
4177  * \param [in] pt the start pointer (included) of the coordinates of the point
4178  * \param [in] cellIdsBg the start pointer (included) of cellIds
4179  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4180  * \param [in] nc nodal connectivity
4181  * \param [in] ncI nodal connectivity index
4182  * \param [in,out] ret0 the min distance between \a this and the external input point
4183  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4184  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4185  */
4186 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)
4187 {
4188   cellId=-1;
4189   ret0=std::numeric_limits<double>::max();
4190   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4191     {
4192       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4193       {
4194         case INTERP_KERNEL::NORM_SEG2:
4195           {
4196             std::size_t uselessEntry=0;
4197             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4198             tmp=sqrt(tmp);
4199             if(tmp<ret0)
4200               { ret0=tmp; cellId=*zeCell; }
4201             break;
4202           }
4203         default:
4204           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4205       }
4206     }
4207 }
4208
4209 /*!
4210  * Finds cells in contact with a ball (i.e. a point with precision). 
4211  * 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.
4212  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4213  *
4214  * \warning This method is suitable if the caller intends to evaluate only one
4215  *          point, for more points getCellsContainingPoints() is recommended as it is
4216  *          faster. 
4217  *  \param [in] pos - array of coordinates of the ball central point.
4218  *  \param [in] eps - ball radius.
4219  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4220  *         if there are no such cells.
4221  *  \throw If the coordinates array is not set.
4222  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4223  */
4224 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4225 {
4226   std::vector<int> elts;
4227   getCellsContainingPoint(pos,eps,elts);
4228   if(elts.empty())
4229     return -1;
4230   return elts.front();
4231 }
4232
4233 /*!
4234  * Finds cells in contact with a ball (i.e. a point with precision).
4235  * 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.
4236  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4237  * \warning This method is suitable if the caller intends to evaluate only one
4238  *          point, for more points getCellsContainingPoints() is recommended as it is
4239  *          faster. 
4240  *  \param [in] pos - array of coordinates of the ball central point.
4241  *  \param [in] eps - ball radius.
4242  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4243  *         before inserting ids.
4244  *  \throw If the coordinates array is not set.
4245  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4246  *
4247  *  \if ENABLE_EXAMPLES
4248  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4249  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4250  *  \endif
4251  */
4252 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4253 {
4254   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4255   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4256   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4257 }
4258
4259 /// @cond INTERNAL
4260
4261 namespace ParaMEDMEM
4262 {
4263   template<const int SPACEDIMM>
4264   class DummyClsMCUG
4265   {
4266   public:
4267     static const int MY_SPACEDIM=SPACEDIMM;
4268     static const int MY_MESHDIM=8;
4269     typedef int MyConnType;
4270     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4271     // begin
4272     // useless, but for windows compilation ...
4273     const double* getCoordinatesPtr() const { return 0; }
4274     const int* getConnectivityPtr() const { return 0; }
4275     const int* getConnectivityIndexPtr() const { return 0; }
4276     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4277     // end
4278   };
4279
4280   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4281   {
4282     INTERP_KERNEL::Edge *ret(0);
4283     MEDCouplingAutoRefCountObjectPtr<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]));
4284     m[n0]=bg[0]; m[n1]=bg[1];
4285     switch(typ)
4286     {
4287       case INTERP_KERNEL::NORM_SEG2:
4288         {
4289           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4290           break;
4291         }
4292       case INTERP_KERNEL::NORM_SEG3:
4293         {
4294           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4295           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4296           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4297           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4298           bool colinearity(inters.areColinears());
4299           delete e1; delete e2;
4300           if(colinearity)
4301             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4302           else
4303             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4304           break;
4305         }
4306       default:
4307         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4308     }
4309     return ret;
4310   }
4311
4312   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4313   {
4314     INTERP_KERNEL::Edge *ret=0;
4315     switch(typ)
4316     {
4317       case INTERP_KERNEL::NORM_SEG2:
4318         {
4319           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4320           break;
4321         }
4322       case INTERP_KERNEL::NORM_SEG3:
4323         {
4324           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4325           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4326           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4327           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4328           bool colinearity=inters.areColinears();
4329           delete e1; delete e2;
4330           if(colinearity)
4331             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4332           else
4333             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4334           mapp2[bg[2]].second=false;
4335           break;
4336         }
4337       default:
4338         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4339     }
4340     return ret;
4341   }
4342
4343   /*!
4344    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4345    * the global mesh 'mDesc'.
4346    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4347    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4348    */
4349   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4350                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4351   {
4352     mapp.clear();
4353     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.
4354     const double *coo=mDesc->getCoords()->getConstPointer();
4355     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4356     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4357     std::set<int> s;
4358     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4359       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4360     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4361       {
4362         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4363         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4364       }
4365     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4366     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4367       {
4368         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4369         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4370       }
4371     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4372       {
4373         if((*it2).second.second)
4374           mapp[(*it2).second.first]=(*it2).first;
4375         ((*it2).second.first)->decrRef();
4376       }
4377     return ret;
4378   }
4379
4380   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4381   {
4382     if(nodeId>=offset2)
4383       {
4384         int locId=nodeId-offset2;
4385         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4386       }
4387     if(nodeId>=offset1)
4388       {
4389         int locId=nodeId-offset1;
4390         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4391       }
4392     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4393   }
4394
4395   /**
4396    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4397    */
4398   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4399                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4400                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4401   {
4402     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4403       {
4404         int eltId1=abs(*desc1)-1;
4405         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4406           {
4407             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4408             if(it==mappRev.end())
4409               {
4410                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4411                 mapp[node]=*it1;
4412                 mappRev[*it1]=node;
4413               }
4414           }
4415       }
4416   }
4417 }
4418
4419 /// @endcond
4420
4421 template<int SPACEDIM>
4422 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4423                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4424 {
4425   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4426   int *eltsIndexPtr(eltsIndex->getPointer());
4427   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4428   const double *bbox(bboxArr->begin());
4429   int nbOfCells=getNumberOfCells();
4430   const int *conn=_nodal_connec->getConstPointer();
4431   const int *connI=_nodal_connec_index->getConstPointer();
4432   double bb[2*SPACEDIM];
4433   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4434   for(int i=0;i<nbOfPoints;i++)
4435     {
4436       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4437       for(int j=0;j<SPACEDIM;j++)
4438         {
4439           bb[2*j]=pos[SPACEDIM*i+j];
4440           bb[2*j+1]=pos[SPACEDIM*i+j];
4441         }
4442       std::vector<int> candidates;
4443       myTree.getIntersectingElems(bb,candidates);
4444       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4445         {
4446           int sz(connI[(*iter)+1]-connI[*iter]-1);
4447           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4448           bool status(false);
4449           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4450             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4451           else
4452             {
4453               if(SPACEDIM!=2)
4454                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4455               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4456               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4457               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4458               INTERP_KERNEL::QuadraticPolygon *pol(0);
4459               for(int j=0;j<sz;j++)
4460                 {
4461                   int nodeId(conn[connI[*iter]+1+j]);
4462                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4463                 }
4464               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4465                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4466               else
4467                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4468               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4469               double a(0.),b(0.),c(0.);
4470               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4471               status=pol->isInOrOut2(n);
4472               delete pol; n->decrRef();
4473             }
4474           if(status)
4475             {
4476               eltsIndexPtr[i+1]++;
4477               elts->pushBackSilent(*iter);
4478             }
4479         }
4480     }
4481 }
4482 /*!
4483  * Finds cells in contact with several balls (i.e. points with precision).
4484  * This method is an extension of getCellContainingPoint() and
4485  * getCellsContainingPoint() for the case of multiple points.
4486  * 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.
4487  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4488  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4489  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4490  *         this->getSpaceDimension() * \a nbOfPoints 
4491  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4492  *  \param [in] eps - radius of balls (i.e. the precision).
4493  *  \param [out] elts - vector returning ids of found cells.
4494  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4495  *         dividing cell ids in \a elts into groups each referring to one
4496  *         point. Its every element (except the last one) is an index pointing to the
4497  *         first id of a group of cells. For example cells in contact with the *i*-th
4498  *         point are described by following range of indices:
4499  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4500  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4501  *         Number of cells in contact with the *i*-th point is
4502  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4503  *  \throw If the coordinates array is not set.
4504  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4505  *
4506  *  \if ENABLE_EXAMPLES
4507  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4508  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4509  *  \endif
4510  */
4511 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4512                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4513 {
4514   int spaceDim=getSpaceDimension();
4515   int mDim=getMeshDimension();
4516   if(spaceDim==3)
4517     {
4518       if(mDim==3)
4519         {
4520           const double *coords=_coords->getConstPointer();
4521           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4522         }
4523       /*else if(mDim==2)
4524         {
4525
4526         }*/
4527       else
4528         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4529     }
4530   else if(spaceDim==2)
4531     {
4532       if(mDim==2)
4533         {
4534           const double *coords=_coords->getConstPointer();
4535           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4536         }
4537       else
4538         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4539     }
4540   else if(spaceDim==1)
4541     {
4542       if(mDim==1)
4543         {
4544           const double *coords=_coords->getConstPointer();
4545           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4546         }
4547       else
4548         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4549     }
4550   else
4551     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4552 }
4553
4554 /*!
4555  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4556  * least two its edges intersect each other anywhere except their extremities. An
4557  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4558  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4559  *         cleared before filling in.
4560  *  \param [in] eps - precision.
4561  *  \throw If \a this->getMeshDimension() != 2.
4562  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4563  */
4564 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4565 {
4566   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4567   if(getMeshDimension()!=2)
4568     throw INTERP_KERNEL::Exception(msg);
4569   int spaceDim=getSpaceDimension();
4570   if(spaceDim!=2 && spaceDim!=3)
4571     throw INTERP_KERNEL::Exception(msg);
4572   const int *conn=_nodal_connec->getConstPointer();
4573   const int *connI=_nodal_connec_index->getConstPointer();
4574   int nbOfCells=getNumberOfCells();
4575   std::vector<double> cell2DinS2;
4576   for(int i=0;i<nbOfCells;i++)
4577     {
4578       int offset=connI[i];
4579       int nbOfNodesForCell=connI[i+1]-offset-1;
4580       if(nbOfNodesForCell<=3)
4581         continue;
4582       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4583       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4584       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4585         cells.push_back(i);
4586       cell2DinS2.clear();
4587     }
4588 }
4589
4590 /*!
4591  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4592  *
4593  * 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.
4594  * 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.
4595  * 
4596  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4597  * This convex envelop is computed using Jarvis march algorithm.
4598  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4599  * 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)
4600  * 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.
4601  *
4602  * \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.
4603  * \sa MEDCouplingUMesh::colinearize2D
4604  */
4605 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4606 {
4607   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4608     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4609   checkFullyDefined();
4610   const double *coords=getCoords()->getConstPointer();
4611   int nbOfCells=getNumberOfCells();
4612   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4613   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4614   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4615   int *workIndexOut=nodalConnecIndexOut->getPointer();
4616   *workIndexOut=0;
4617   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4618   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4619   std::set<INTERP_KERNEL::NormalizedCellType> types;
4620   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4621   isChanged->alloc(0,1);
4622   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4623     {
4624       int pos=nodalConnecOut->getNumberOfTuples();
4625       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4626         isChanged->pushBackSilent(i);
4627       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4628       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4629     }
4630   if(isChanged->empty())
4631     return 0;
4632   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4633   _types=types;
4634   return isChanged.retn();
4635 }
4636
4637 /*!
4638  * This method is \b NOT const because it can modify \a this.
4639  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4640  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4641  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4642  * \b 1 for translation and rotation around point of 'mesh1D'.
4643  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4644  */
4645 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4646 {
4647   checkFullyDefined();
4648   mesh1D->checkFullyDefined();
4649   if(!mesh1D->isContiguous1D())
4650     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4651   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4652     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4653   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4654     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4655   if(mesh1D->getMeshDimension()!=1)
4656     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4657   bool isQuad=false;
4658   if(isPresenceOfQuadratic())
4659     {
4660       if(mesh1D->isFullyQuadratic())
4661         isQuad=true;
4662       else
4663         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4664     }
4665   int oldNbOfNodes(getNumberOfNodes());
4666   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4667   switch(policy)
4668   {
4669     case 0:
4670       {
4671         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4672         break;
4673       }
4674     case 1:
4675       {
4676         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4677         break;
4678       }
4679     default:
4680       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4681   }
4682   setCoords(newCoords);
4683   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4684   updateTime();
4685   return ret.retn();
4686 }
4687
4688 /*!
4689  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4690  * If it is not the case an exception will be thrown.
4691  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4692  * intersection of plane defined by ('origin','vec').
4693  * This method has one in/out parameter : 'cut3DCurve'.
4694  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4695  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4696  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4697  * This method will throw an exception if \a this contains a non linear segment.
4698  */
4699 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4700 {
4701   checkFullyDefined();
4702   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4703     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4704   int ncells=getNumberOfCells();
4705   int nnodes=getNumberOfNodes();
4706   double vec2[3],vec3[3],vec4[3];
4707   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4708   if(normm<1e-6)
4709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4710   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4711   const int *conn=_nodal_connec->getConstPointer();
4712   const int *connI=_nodal_connec_index->getConstPointer();
4713   const double *coo=_coords->getConstPointer();
4714   std::vector<double> addCoo;
4715   for(int i=0;i<ncells;i++)
4716     {
4717       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4718         {
4719           if(cut3DCurve[i]==-2)
4720             {
4721               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4722               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];
4723               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4724               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4725               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4726                 {
4727                   const double *st2=coo+3*st;
4728                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4729                   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]));
4730                   if(pos>eps && pos<1-eps)
4731                     {
4732                       int nNode=((int)addCoo.size())/3;
4733                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4734                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4735                       cut3DCurve[i]=nnodes+nNode;
4736                     }
4737                 }
4738             }
4739         }
4740       else
4741         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4742     }
4743   if(!addCoo.empty())
4744     {
4745       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4746       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4747       coo2->alloc(newNbOfNodes,3);
4748       double *tmp=coo2->getPointer();
4749       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4750       std::copy(addCoo.begin(),addCoo.end(),tmp);
4751       DataArrayDouble::SetArrayIn(coo2,_coords);
4752     }
4753 }
4754
4755 /*!
4756  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4757  * \param mesh1D is the input 1D mesh used for translation computation.
4758  * \return newCoords new coords filled by this method. 
4759  */
4760 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4761 {
4762   int oldNbOfNodes=getNumberOfNodes();
4763   int nbOf1DCells=mesh1D->getNumberOfCells();
4764   int spaceDim=getSpaceDimension();
4765   DataArrayDouble *ret=DataArrayDouble::New();
4766   std::vector<bool> isQuads;
4767   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4768   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4769   double *retPtr=ret->getPointer();
4770   const double *coords=getCoords()->getConstPointer();
4771   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4772   std::vector<int> v;
4773   std::vector<double> c;
4774   double vec[3];
4775   v.reserve(3);
4776   c.reserve(6);
4777   for(int i=0;i<nbOf1DCells;i++)
4778     {
4779       v.resize(0);
4780       mesh1D->getNodeIdsOfCell(i,v);
4781       c.resize(0);
4782       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4783       mesh1D->getCoordinatesOfNode(v[0],c);
4784       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4785       for(int j=0;j<oldNbOfNodes;j++)
4786         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4787       if(isQuad)
4788         {
4789           c.resize(0);
4790           mesh1D->getCoordinatesOfNode(v[1],c);
4791           mesh1D->getCoordinatesOfNode(v[0],c);
4792           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4793           for(int j=0;j<oldNbOfNodes;j++)
4794             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4795         }
4796     }
4797   ret->copyStringInfoFrom(*getCoords());
4798   return ret;
4799 }
4800
4801 /*!
4802  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4803  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4804  * \return newCoords new coords filled by this method. 
4805  */
4806 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4807 {
4808   if(mesh1D->getSpaceDimension()==2)
4809     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4810   if(mesh1D->getSpaceDimension()==3)
4811     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4812   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4813 }
4814
4815 /*!
4816  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4817  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4818  * \return newCoords new coords filled by this method. 
4819  */
4820 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4821 {
4822   if(isQuad)
4823     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4824   int oldNbOfNodes=getNumberOfNodes();
4825   int nbOf1DCells=mesh1D->getNumberOfCells();
4826   if(nbOf1DCells<2)
4827     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4828   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4829   int nbOfLevsInVec=nbOf1DCells+1;
4830   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4831   double *retPtr=ret->getPointer();
4832   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4833   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4834   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4835   tmp->setCoords(tmp2);
4836   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4837   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4838   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4839   for(int i=1;i<nbOfLevsInVec;i++)
4840     {
4841       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4842       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4843       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4844       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4845       tmp->translate(vec);
4846       double tmp3[2],radius,alpha,alpha0;
4847       const double *p0=i+1<nbOfLevsInVec?begin:third;
4848       const double *p1=i+1<nbOfLevsInVec?end:begin;
4849       const double *p2=i+1<nbOfLevsInVec?third:end;
4850       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4851       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]);
4852       double angle=acos(cosangle/(radius*radius));
4853       tmp->rotate(end,0,angle);
4854       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4855     }
4856   return ret.retn();
4857 }
4858
4859 /*!
4860  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4861  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4862  * \return newCoords new coords filled by this method. 
4863  */
4864 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4865 {
4866   if(isQuad)
4867     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4868   int oldNbOfNodes=getNumberOfNodes();
4869   int nbOf1DCells=mesh1D->getNumberOfCells();
4870   if(nbOf1DCells<2)
4871     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4872   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4873   int nbOfLevsInVec=nbOf1DCells+1;
4874   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4875   double *retPtr=ret->getPointer();
4876   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4877   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4878   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4879   tmp->setCoords(tmp2);
4880   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4881   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4882   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4883   for(int i=1;i<nbOfLevsInVec;i++)
4884     {
4885       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4886       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4887       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4888       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4889       tmp->translate(vec);
4890       double tmp3[2],radius,alpha,alpha0;
4891       const double *p0=i+1<nbOfLevsInVec?begin:third;
4892       const double *p1=i+1<nbOfLevsInVec?end:begin;
4893       const double *p2=i+1<nbOfLevsInVec?third:end;
4894       double vecPlane[3]={
4895         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4896         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4897         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4898       };
4899       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4900       if(norm>1.e-7)
4901         {
4902           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4903           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4904           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4905           double s2=norm2;
4906           double c2=cos(asin(s2));
4907           double m[3][3]={
4908             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4909             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4910             {-vec2[1]*s2, vec2[0]*s2, c2}
4911           };
4912           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]};
4913           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]};
4914           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]};
4915           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4916           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]);
4917           double angle=acos(cosangle/(radius*radius));
4918           tmp->rotate(end,vecPlane,angle);
4919         }
4920       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4921     }
4922   return ret.retn();
4923 }
4924
4925 /*!
4926  * This method is private because not easy to use for end user. This method is const contrary to
4927  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4928  * the coords sorted slice by slice.
4929  * \param isQuad specifies presence of quadratic cells.
4930  */
4931 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4932 {
4933   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4934   int nbOf2DCells(getNumberOfCells());
4935   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4936   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4937   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4938   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4939   newConnI->alloc(nbOf3DCells+1,1);
4940   int *newConnIPtr(newConnI->getPointer());
4941   *newConnIPtr++=0;
4942   std::vector<int> newc;
4943   for(int j=0;j<nbOf2DCells;j++)
4944     {
4945       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4946       *newConnIPtr++=(int)newc.size();
4947     }
4948   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4949   int *newConnPtr(newConn->getPointer());
4950   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4951   newConnIPtr=newConnI->getPointer();
4952   for(int iz=0;iz<nbOf1DCells;iz++)
4953     {
4954       if(iz!=0)
4955         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4956       const int *posOfTypeOfCell(newConnIPtr);
4957       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4958         {
4959           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4960           if(icell!=*posOfTypeOfCell)
4961             {
4962               if(*iter!=-1)
4963                 *newConnPtr=(*iter)+iz*deltaPerLev;
4964               else
4965                 *newConnPtr=-1;
4966             }
4967           else
4968             {
4969               *newConnPtr=*iter;
4970               posOfTypeOfCell++;
4971             }
4972         }
4973     }
4974   ret->setConnectivity(newConn,newConnI,true);
4975   ret->setCoords(getCoords());
4976   return ret;
4977 }
4978
4979 /*!
4980  * Checks if \a this mesh is constituted by only quadratic cells.
4981  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4982  *  \throw If the coordinates array is not set.
4983  *  \throw If the nodal connectivity of cells is not defined.
4984  */
4985 bool MEDCouplingUMesh::isFullyQuadratic() const
4986 {
4987   checkFullyDefined();
4988   bool ret=true;
4989   int nbOfCells=getNumberOfCells();
4990   for(int i=0;i<nbOfCells && ret;i++)
4991     {
4992       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4993       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4994       ret=cm.isQuadratic();
4995     }
4996   return ret;
4997 }
4998
4999 /*!
5000  * Checks if \a this mesh includes any quadratic cell.
5001  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5002  *  \throw If the coordinates array is not set.
5003  *  \throw If the nodal connectivity of cells is not defined.
5004  */
5005 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5006 {
5007   checkFullyDefined();
5008   bool ret=false;
5009   int nbOfCells=getNumberOfCells();
5010   for(int i=0;i<nbOfCells && !ret;i++)
5011     {
5012       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5013       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5014       ret=cm.isQuadratic();
5015     }
5016   return ret;
5017 }
5018
5019 /*!
5020  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5021  * this mesh, it remains unchanged.
5022  *  \throw If the coordinates array is not set.
5023  *  \throw If the nodal connectivity of cells is not defined.
5024  */
5025 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5026 {
5027   checkFullyDefined();
5028   int nbOfCells=getNumberOfCells();
5029   int delta=0;
5030   const int *iciptr=_nodal_connec_index->getConstPointer();
5031   for(int i=0;i<nbOfCells;i++)
5032     {
5033       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5034       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5035       if(cm.isQuadratic())
5036         {
5037           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5038           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5039           if(!cml.isDynamic())
5040             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5041           else
5042             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5043         }
5044     }
5045   if(delta==0)
5046     return ;
5047   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5048   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5049   const int *icptr=_nodal_connec->getConstPointer();
5050   newConn->alloc(getMeshLength()-delta,1);
5051   newConnI->alloc(nbOfCells+1,1);
5052   int *ocptr=newConn->getPointer();
5053   int *ociptr=newConnI->getPointer();
5054   *ociptr=0;
5055   _types.clear();
5056   for(int i=0;i<nbOfCells;i++,ociptr++)
5057     {
5058       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5059       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5060       if(!cm.isQuadratic())
5061         {
5062           _types.insert(type);
5063           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5064           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5065         }
5066       else
5067         {
5068           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5069           _types.insert(typel);
5070           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5071           int newNbOfNodes=cml.getNumberOfNodes();
5072           if(cml.isDynamic())
5073             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5074           *ocptr++=(int)typel;
5075           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5076           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5077         }
5078     }
5079   setConnectivity(newConn,newConnI,false);
5080 }
5081
5082 /*!
5083  * This method converts all linear cell in \a this to quadratic one.
5084  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5085  * 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)
5086  * 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.
5087  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5088  * end of the existing coordinates.
5089  * 
5090  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5091  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5092  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5093  * 
5094  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5095  *
5096  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5097  */
5098 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5099 {
5100   DataArrayInt *conn=0,*connI=0;
5101   DataArrayDouble *coords=0;
5102   std::set<INTERP_KERNEL::NormalizedCellType> types;
5103   checkFullyDefined();
5104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5105   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5106   int meshDim=getMeshDimension();
5107   switch(conversionType)
5108   {
5109     case 0:
5110       switch(meshDim)
5111       {
5112         case 1:
5113           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5114           connSafe=conn; connISafe=connI; coordsSafe=coords;
5115           break;
5116         case 2:
5117           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5118           connSafe=conn; connISafe=connI; coordsSafe=coords;
5119           break;
5120         case 3:
5121           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5122           connSafe=conn; connISafe=connI; coordsSafe=coords;
5123           break;
5124         default:
5125           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5126       }
5127       break;
5128         case 1:
5129           {
5130             switch(meshDim)
5131             {
5132               case 1:
5133                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5134                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5135                 break;
5136               case 2:
5137                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5138                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5139                 break;
5140               case 3:
5141                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5142                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5143                 break;
5144               default:
5145                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5146             }
5147             break;
5148           }
5149         default:
5150           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5151   }
5152   setConnectivity(connSafe,connISafe,false);
5153   _types=types;
5154   setCoords(coordsSafe);
5155   return ret.retn();
5156 }
5157
5158 #if 0
5159 /*!
5160  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5161  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5162  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5163  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5164  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5165  * This method can be seen as the opposite method of colinearize2D.
5166  * 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
5167  * to avoid to modify the numbering of existing nodes.
5168  *
5169  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5170  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5171  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5172  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5173  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5174  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5175  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5176  *
5177  * \sa buildDescendingConnectivity2
5178  */
5179 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5180                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5181 {
5182   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5183     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5184   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5185   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5186     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5187   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5188     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5189   //DataArrayInt *out0(0),*outi0(0);
5190   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5191   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5192   //out0s=out0s->buildUnique(); out0s->sort(true);
5193 }
5194 #endif
5195
5196 /*!
5197  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5198  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5199  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5200  */
5201 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5202 {
5203   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5204   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5205   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5206   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5207   int nbOfCells=getNumberOfCells();
5208   int nbOfNodes=getNumberOfNodes();
5209   const int *cPtr=_nodal_connec->getConstPointer();
5210   const int *icPtr=_nodal_connec_index->getConstPointer();
5211   int lastVal=0,offset=nbOfNodes;
5212   for(int i=0;i<nbOfCells;i++,icPtr++)
5213     {
5214       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5215       if(type==INTERP_KERNEL::NORM_SEG2)
5216         {
5217           types.insert(INTERP_KERNEL::NORM_SEG3);
5218           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5219           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5220           newConn->pushBackSilent(offset++);
5221           lastVal+=4;
5222           newConnI->pushBackSilent(lastVal);
5223           ret->pushBackSilent(i);
5224         }
5225       else
5226         {
5227           types.insert(type);
5228           lastVal+=(icPtr[1]-icPtr[0]);
5229           newConnI->pushBackSilent(lastVal);
5230           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5231         }
5232     }
5233   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5234   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5235   return ret.retn();
5236 }
5237
5238 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
5239 {
5240   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5243   //
5244   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5245   DataArrayInt *conn1D=0,*conn1DI=0;
5246   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5247   DataArrayDouble *coordsTmp=0;
5248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5249   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5250   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5251   const int *c1DPtr=conn1D->begin();
5252   const int *c1DIPtr=conn1DI->begin();
5253   int nbOfCells=getNumberOfCells();
5254   const int *cPtr=_nodal_connec->getConstPointer();
5255   const int *icPtr=_nodal_connec_index->getConstPointer();
5256   int lastVal=0;
5257   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5258     {
5259       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5260       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5261       if(!cm.isQuadratic())
5262         {
5263           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5264           types.insert(typ2); newConn->pushBackSilent(typ2);
5265           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5266           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5267             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5268           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5269           newConnI->pushBackSilent(lastVal);
5270           ret->pushBackSilent(i);
5271         }
5272       else
5273         {
5274           types.insert(typ);
5275           lastVal+=(icPtr[1]-icPtr[0]);
5276           newConnI->pushBackSilent(lastVal);
5277           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5278         }
5279     }
5280   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5281   return ret.retn();
5282 }
5283
5284 /*!
5285  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5286  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5287  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5288  */
5289 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5290 {
5291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5292   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5293   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5294 }
5295
5296 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5297 {
5298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5299   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5300   //
5301   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5302   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5303   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5304   //
5305   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5306   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5307   DataArrayInt *conn1D=0,*conn1DI=0;
5308   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5309   DataArrayDouble *coordsTmp=0;
5310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5311   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5312   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5313   const int *c1DPtr=conn1D->begin();
5314   const int *c1DIPtr=conn1DI->begin();
5315   int nbOfCells=getNumberOfCells();
5316   const int *cPtr=_nodal_connec->getConstPointer();
5317   const int *icPtr=_nodal_connec_index->getConstPointer();
5318   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5319   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5320     {
5321       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5322       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5323       if(!cm.isQuadratic())
5324         {
5325           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5326           types.insert(typ2); newConn->pushBackSilent(typ2);
5327           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5328           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5329             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5330           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5331           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5332           newConnI->pushBackSilent(lastVal);
5333           ret->pushBackSilent(i);
5334         }
5335       else
5336         {
5337           types.insert(typ);
5338           lastVal+=(icPtr[1]-icPtr[0]);
5339           newConnI->pushBackSilent(lastVal);
5340           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5341         }
5342     }
5343   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5344   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5345   return ret.retn();
5346 }
5347
5348 /*!
5349  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5350  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5351  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5352  */
5353 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5354 {
5355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5356   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5357   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5358 }
5359
5360 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5361 {
5362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5363   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5364   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5365   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5366   //
5367   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5370   //
5371   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5372   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5373   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5374   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5375   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5378   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5380   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5382   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5383   int nbOfCells=getNumberOfCells();
5384   const int *cPtr=_nodal_connec->getConstPointer();
5385   const int *icPtr=_nodal_connec_index->getConstPointer();
5386   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5387   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5388     {
5389       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5390       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5391       if(!cm.isQuadratic())
5392         {
5393           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5394           if(typ2==INTERP_KERNEL::NORM_ERROR)
5395             {
5396               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5397               throw INTERP_KERNEL::Exception(oss.str().c_str());
5398             }
5399           types.insert(typ2); newConn->pushBackSilent(typ2);
5400           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5401           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5402             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5403           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5404             {
5405               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5406               int tmpPos=newConn->getNumberOfTuples();
5407               newConn->pushBackSilent(nodeId2);
5408               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5409             }
5410           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5411           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5412           newConnI->pushBackSilent(lastVal);
5413           ret->pushBackSilent(i);
5414         }
5415       else
5416         {
5417           types.insert(typ);
5418           lastVal+=(icPtr[1]-icPtr[0]);
5419           newConnI->pushBackSilent(lastVal);
5420           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5421         }
5422     }
5423   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5424   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5425   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5426   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5427   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5428   int *c=newConn->getPointer();
5429   const int *cI(newConnI->begin());
5430   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5431     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5432   offset=coordsTmp2Safe->getNumberOfTuples();
5433   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5434     c[cI[(*elt)+1]-1]+=offset;
5435   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5436   return ret.retn();
5437 }
5438
5439 /*!
5440  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5441  * so that the number of cells remains the same. Quadratic faces are converted to
5442  * polygons. This method works only for 2D meshes in
5443  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5444  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5445  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5446  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5447  *         a polylinized edge constituting the input polygon.
5448  *  \throw If the coordinates array is not set.
5449  *  \throw If the nodal connectivity of cells is not defined.
5450  *  \throw If \a this->getMeshDimension() != 2.
5451  *  \throw If \a this->getSpaceDimension() != 2.
5452  */
5453 void MEDCouplingUMesh::tessellate2D(double eps)
5454 {
5455   checkFullyDefined();
5456   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5457     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5458   double epsa=fabs(eps);
5459   if(epsa<std::numeric_limits<double>::min())
5460     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5461   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5463   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5465   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5466   revDesc1=0; revDescIndx1=0;
5467   mDesc->tessellate2DCurve(eps);
5468   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5469   setCoords(mDesc->getCoords());
5470 }
5471
5472 /*!
5473  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5474  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5475  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5476  *         a sub-divided edge.
5477  *  \throw If the coordinates array is not set.
5478  *  \throw If the nodal connectivity of cells is not defined.
5479  *  \throw If \a this->getMeshDimension() != 1.
5480  *  \throw If \a this->getSpaceDimension() != 2.
5481  */
5482 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5483 {
5484   checkFullyDefined();
5485   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5486     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5487   double epsa=fabs(eps);
5488   if(epsa<std::numeric_limits<double>::min())
5489     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5490   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5491   int nbCells=getNumberOfCells();
5492   int nbNodes=getNumberOfNodes();
5493   const int *conn=_nodal_connec->getConstPointer();
5494   const int *connI=_nodal_connec_index->getConstPointer();
5495   const double *coords=_coords->getConstPointer();
5496   std::vector<double> addCoo;
5497   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5498   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5499   newConnI->alloc(nbCells+1,1);
5500   int *newConnIPtr=newConnI->getPointer();
5501   *newConnIPtr=0;
5502   int tmp1[3];
5503   INTERP_KERNEL::Node *tmp2[3];
5504   std::set<INTERP_KERNEL::NormalizedCellType> types;
5505   for(int i=0;i<nbCells;i++,newConnIPtr++)
5506     {
5507       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5508       if(cm.isQuadratic())
5509         {//assert(connI[i+1]-connI[i]-1==3)
5510           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5511           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5512           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5513           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5514           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5515           if(eac)
5516             {
5517               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5518               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5519               delete eac;
5520               newConnIPtr[1]=(int)newConn.size();
5521             }
5522           else
5523             {
5524               types.insert(INTERP_KERNEL::NORM_SEG2);
5525               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5526               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5527               newConnIPtr[1]=newConnIPtr[0]+3;
5528             }
5529         }
5530       else
5531         {
5532           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5533           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5534           newConnIPtr[1]=newConnIPtr[0]+3;
5535         }
5536     }
5537   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5538     return ;
5539   _types=types;
5540   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5541   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5542   newConnArr->alloc((int)newConn.size(),1);
5543   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5544   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5545   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5546   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5547   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5548   std::copy(addCoo.begin(),addCoo.end(),work);
5549   DataArrayDouble::SetArrayIn(newCoords,_coords);
5550   updateTime();
5551 }
5552
5553 /*!
5554  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5555  * In addition, returns an array mapping new cells to old ones. <br>
5556  * This method typically increases the number of cells in \a this mesh
5557  * but the number of nodes remains \b unchanged.
5558  * That's why the 3D splitting policies
5559  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5560  *  \param [in] policy - specifies a pattern used for splitting.
5561  * The semantic of \a policy is:
5562  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5563  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5564  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5565  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5566  *
5567  *
5568  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5569  *          an id of old cell producing it. The caller is to delete this array using
5570  *         decrRef() as it is no more needed.
5571  *
5572  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5573  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5574  *          and \a this->getMeshDimension() != 3. 
5575  *  \throw If \a policy is not one of the four discussed above.
5576  *  \throw If the nodal connectivity of cells is not defined.
5577  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5578  */
5579 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5580 {
5581   switch(policy)
5582   {
5583     case 0:
5584       return simplexizePol0();
5585     case 1:
5586       return simplexizePol1();
5587     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5588         return simplexizePlanarFace5();
5589     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5590         return simplexizePlanarFace6();
5591     default:
5592       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)");
5593   }
5594 }
5595
5596 /*!
5597  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5598  * - 1D: INTERP_KERNEL::NORM_SEG2
5599  * - 2D: INTERP_KERNEL::NORM_TRI3
5600  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5601  *
5602  * This method is useful for users that need to use P1 field services as
5603  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5604  * All these methods need mesh support containing only simplex cells.
5605  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5606  *  \throw If the coordinates array is not set.
5607  *  \throw If the nodal connectivity of cells is not defined.
5608  *  \throw If \a this->getMeshDimension() < 1.
5609  */
5610 bool MEDCouplingUMesh::areOnlySimplexCells() const
5611 {
5612   checkFullyDefined();
5613   int mdim=getMeshDimension();
5614   if(mdim<1 || mdim>3)
5615     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5616   int nbCells=getNumberOfCells();
5617   const int *conn=_nodal_connec->getConstPointer();
5618   const int *connI=_nodal_connec_index->getConstPointer();
5619   for(int i=0;i<nbCells;i++)
5620     {
5621       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5622       if(!cm.isSimplex())
5623         return false;
5624     }
5625   return true;
5626 }
5627
5628 /*!
5629  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5630  */
5631 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5632 {
5633   checkConnectivityFullyDefined();
5634   if(getMeshDimension()!=2)
5635     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5636   int nbOfCells=getNumberOfCells();
5637   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5638   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5639   ret->alloc(nbOfCells+nbOfCutCells,1);
5640   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5641   int *retPt=ret->getPointer();
5642   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5643   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5644   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5645   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5646   int *pt=newConn->getPointer();
5647   int *ptI=newConnI->getPointer();
5648   ptI[0]=0;
5649   const int *oldc=_nodal_connec->getConstPointer();
5650   const int *ci=_nodal_connec_index->getConstPointer();
5651   for(int i=0;i<nbOfCells;i++,ci++)
5652     {
5653       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5654         {
5655           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5656             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5657           pt=std::copy(tmp,tmp+8,pt);
5658           ptI[1]=ptI[0]+4;
5659           ptI[2]=ptI[0]+8;
5660           *retPt++=i;
5661           *retPt++=i;
5662           ptI+=2;
5663         }
5664       else
5665         {
5666           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5667           ptI[1]=ptI[0]+ci[1]-ci[0];
5668           ptI++;
5669           *retPt++=i;
5670         }
5671     }
5672   _nodal_connec->decrRef();
5673   _nodal_connec=newConn.retn();
5674   _nodal_connec_index->decrRef();
5675   _nodal_connec_index=newConnI.retn();
5676   computeTypes();
5677   updateTime();
5678   return ret.retn();
5679 }
5680
5681 /*!
5682  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5683  */
5684 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5685 {
5686   checkConnectivityFullyDefined();
5687   if(getMeshDimension()!=2)
5688     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5689   int nbOfCells=getNumberOfCells();
5690   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5691   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5692   ret->alloc(nbOfCells+nbOfCutCells,1);
5693   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5694   int *retPt=ret->getPointer();
5695   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5696   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5697   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5698   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5699   int *pt=newConn->getPointer();
5700   int *ptI=newConnI->getPointer();
5701   ptI[0]=0;
5702   const int *oldc=_nodal_connec->getConstPointer();
5703   const int *ci=_nodal_connec_index->getConstPointer();
5704   for(int i=0;i<nbOfCells;i++,ci++)
5705     {
5706       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5707         {
5708           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5709             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5710           pt=std::copy(tmp,tmp+8,pt);
5711           ptI[1]=ptI[0]+4;
5712           ptI[2]=ptI[0]+8;
5713           *retPt++=i;
5714           *retPt++=i;
5715           ptI+=2;
5716         }
5717       else
5718         {
5719           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5720           ptI[1]=ptI[0]+ci[1]-ci[0];
5721           ptI++;
5722           *retPt++=i;
5723         }
5724     }
5725   _nodal_connec->decrRef();
5726   _nodal_connec=newConn.retn();
5727   _nodal_connec_index->decrRef();
5728   _nodal_connec_index=newConnI.retn();
5729   computeTypes();
5730   updateTime();
5731   return ret.retn();
5732 }
5733
5734 /*!
5735  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5736  */
5737 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5738 {
5739   checkConnectivityFullyDefined();
5740   if(getMeshDimension()!=3)
5741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5742   int nbOfCells=getNumberOfCells();
5743   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5744   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5745   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5746   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5747   int *retPt=ret->getPointer();
5748   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5749   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5750   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5751   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5752   int *pt=newConn->getPointer();
5753   int *ptI=newConnI->getPointer();
5754   ptI[0]=0;
5755   const int *oldc=_nodal_connec->getConstPointer();
5756   const int *ci=_nodal_connec_index->getConstPointer();
5757   for(int i=0;i<nbOfCells;i++,ci++)
5758     {
5759       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5760         {
5761           for(int j=0;j<5;j++,pt+=5,ptI++)
5762             {
5763               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5764               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];
5765               *retPt++=i;
5766               ptI[1]=ptI[0]+5;
5767             }
5768         }
5769       else
5770         {
5771           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5772           ptI[1]=ptI[0]+ci[1]-ci[0];
5773           ptI++;
5774           *retPt++=i;
5775         }
5776     }
5777   _nodal_connec->decrRef();
5778   _nodal_connec=newConn.retn();
5779   _nodal_connec_index->decrRef();
5780   _nodal_connec_index=newConnI.retn();
5781   computeTypes();
5782   updateTime();
5783   return ret.retn();
5784 }
5785
5786 /*!
5787  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5788  */
5789 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5790 {
5791   checkConnectivityFullyDefined();
5792   if(getMeshDimension()!=3)
5793     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5794   int nbOfCells=getNumberOfCells();
5795   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5796   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5797   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5798   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5799   int *retPt=ret->getPointer();
5800   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5801   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5802   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5803   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5804   int *pt=newConn->getPointer();
5805   int *ptI=newConnI->getPointer();
5806   ptI[0]=0;
5807   const int *oldc=_nodal_connec->getConstPointer();
5808   const int *ci=_nodal_connec_index->getConstPointer();
5809   for(int i=0;i<nbOfCells;i++,ci++)
5810     {
5811       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5812         {
5813           for(int j=0;j<6;j++,pt+=5,ptI++)
5814             {
5815               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5816               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];
5817               *retPt++=i;
5818               ptI[1]=ptI[0]+5;
5819             }
5820         }
5821       else
5822         {
5823           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5824           ptI[1]=ptI[0]+ci[1]-ci[0];
5825           ptI++;
5826           *retPt++=i;
5827         }
5828     }
5829   _nodal_connec->decrRef();
5830   _nodal_connec=newConn.retn();
5831   _nodal_connec_index->decrRef();
5832   _nodal_connec_index=newConnI.retn();
5833   computeTypes();
5834   updateTime();
5835   return ret.retn();
5836 }
5837
5838 /*!
5839  * 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.
5840  * This method completly ignore coordinates.
5841  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5842  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5843  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5844  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5845  */
5846 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5847 {
5848   checkFullyDefined();
5849   if(getMeshDimension()!=2)
5850     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5851   int nbOfCells=getNumberOfCells();
5852   int *connI=_nodal_connec_index->getPointer();
5853   int newConnLgth=0;
5854   for(int i=0;i<nbOfCells;i++,connI++)
5855     {
5856       int offset=descIndex[i];
5857       int nbOfEdges=descIndex[i+1]-offset;
5858       //
5859       bool ddirect=desc[offset+nbOfEdges-1]>0;
5860       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5861       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5862       for(int j=0;j<nbOfEdges;j++)
5863         {
5864           bool direct=desc[offset+j]>0;
5865           int edgeId=std::abs(desc[offset+j])-1;
5866           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5867             {
5868               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5869               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5870               int ref2=direct?id1:id2;
5871               if(ref==ref2)
5872                 {
5873                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5874                   newConnLgth+=nbOfSubNodes-1;
5875                   ref=direct?id2:id1;
5876                 }
5877               else
5878                 {
5879                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5880                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5881                 }
5882             }
5883           else
5884             {
5885               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5886             }
5887         }
5888       newConnLgth++;//+1 is for cell type
5889       connI[1]=newConnLgth;
5890     }
5891   //
5892   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5893   newConn->alloc(newConnLgth,1);
5894   int *work=newConn->getPointer();
5895   for(int i=0;i<nbOfCells;i++)
5896     {
5897       *work++=INTERP_KERNEL::NORM_POLYGON;
5898       int offset=descIndex[i];
5899       int nbOfEdges=descIndex[i+1]-offset;
5900       for(int j=0;j<nbOfEdges;j++)
5901         {
5902           bool direct=desc[offset+j]>0;
5903           int edgeId=std::abs(desc[offset+j])-1;
5904           if(direct)
5905             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5906           else
5907             {
5908               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5909               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5910               work=std::copy(it,it+nbOfSubNodes-1,work);
5911             }
5912         }
5913     }
5914   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5915   _types.clear();
5916   if(nbOfCells>0)
5917     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5918 }
5919
5920 /*!
5921  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5922  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5923  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5924  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5925  * so it can be useful to call mergeNodes() before calling this method.
5926  *  \throw If \a this->getMeshDimension() <= 1.
5927  *  \throw If the coordinates array is not set.
5928  *  \throw If the nodal connectivity of cells is not defined.
5929  */
5930 void MEDCouplingUMesh::convertDegeneratedCells()
5931 {
5932   checkFullyDefined();
5933   if(getMeshDimension()<=1)
5934     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5935   int nbOfCells=getNumberOfCells();
5936   if(nbOfCells<1)
5937     return ;
5938   int initMeshLgth=getMeshLength();
5939   int *conn=_nodal_connec->getPointer();
5940   int *index=_nodal_connec_index->getPointer();
5941   int posOfCurCell=0;
5942   int newPos=0;
5943   int lgthOfCurCell;
5944   for(int i=0;i<nbOfCells;i++)
5945     {
5946       lgthOfCurCell=index[i+1]-posOfCurCell;
5947       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5948       int newLgth;
5949       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5950                                                                                                      conn+newPos+1,newLgth);
5951       conn[newPos]=newType;
5952       newPos+=newLgth+1;
5953       posOfCurCell=index[i+1];
5954       index[i+1]=newPos;
5955     }
5956   if(newPos!=initMeshLgth)
5957     _nodal_connec->reAlloc(newPos);
5958   computeTypes();
5959 }
5960
5961 /*!
5962  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5963  * A cell is considered to be oriented correctly if an angle between its
5964  * normal vector and a given vector is less than \c PI / \c 2.
5965  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5966  *         cells. 
5967  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5968  *         checked.
5969  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5970  *         is not cleared before filling in.
5971  *  \throw If \a this->getMeshDimension() != 2.
5972  *  \throw If \a this->getSpaceDimension() != 3.
5973  *
5974  *  \if ENABLE_EXAMPLES
5975  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5976  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5977  *  \endif
5978  */
5979 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5980 {
5981   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5982     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5983   int nbOfCells=getNumberOfCells();
5984   const int *conn=_nodal_connec->getConstPointer();
5985   const int *connI=_nodal_connec_index->getConstPointer();
5986   const double *coordsPtr=_coords->getConstPointer();
5987   for(int i=0;i<nbOfCells;i++)
5988     {
5989       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5990       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5991         {
5992           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5993           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5994             cells.push_back(i);
5995         }
5996     }
5997 }
5998
5999 /*!
6000  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6001  * considered to be oriented correctly if an angle between its normal vector and a
6002  * given vector is less than \c PI / \c 2. 
6003  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6004  *         cells. 
6005  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6006  *         checked.
6007  *  \throw If \a this->getMeshDimension() != 2.
6008  *  \throw If \a this->getSpaceDimension() != 3.
6009  *
6010  *  \if ENABLE_EXAMPLES
6011  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6012  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6013  *  \endif
6014  *
6015  *  \sa changeOrientationOfCells
6016  */
6017 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6018 {
6019   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6020     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6021   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6022   const int *connI(_nodal_connec_index->getConstPointer());
6023   const double *coordsPtr(_coords->getConstPointer());
6024   bool isModified(false);
6025   for(int i=0;i<nbOfCells;i++)
6026     {
6027       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6028       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6029         {
6030           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6031           bool isQuadratic(cm.isQuadratic());
6032           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6033             {
6034               isModified=true;
6035               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6036             }
6037         }
6038     }
6039   if(isModified)
6040     _nodal_connec->declareAsNew();
6041   updateTime();
6042 }
6043
6044 /*!
6045  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6046  *
6047  * \sa orientCorrectly2DCells
6048  */
6049 void MEDCouplingUMesh::changeOrientationOfCells()
6050 {
6051   int mdim(getMeshDimension());
6052   if(mdim!=2 && mdim!=1)
6053     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6054   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6055   const int *connI(_nodal_connec_index->getConstPointer());
6056   if(mdim==2)
6057     {//2D
6058       for(int i=0;i<nbOfCells;i++)
6059         {
6060           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6061           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6062           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6063         }
6064     }
6065   else
6066     {//1D
6067       for(int i=0;i<nbOfCells;i++)
6068         {
6069           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6070           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6071           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6072         }
6073     }
6074 }
6075
6076 /*!
6077  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6078  * oriented facets. The normal vector of the facet should point out of the cell.
6079  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6080  *         is not cleared before filling in.
6081  *  \throw If \a this->getMeshDimension() != 3.
6082  *  \throw If \a this->getSpaceDimension() != 3.
6083  *  \throw If the coordinates array is not set.
6084  *  \throw If the nodal connectivity of cells is not defined.
6085  *
6086  *  \if ENABLE_EXAMPLES
6087  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6088  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6089  *  \endif
6090  */
6091 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6092 {
6093   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6094     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6095   int nbOfCells=getNumberOfCells();
6096   const int *conn=_nodal_connec->getConstPointer();
6097   const int *connI=_nodal_connec_index->getConstPointer();
6098   const double *coordsPtr=_coords->getConstPointer();
6099   for(int i=0;i<nbOfCells;i++)
6100     {
6101       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6102       if(type==INTERP_KERNEL::NORM_POLYHED)
6103         {
6104           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6105             cells.push_back(i);
6106         }
6107     }
6108 }
6109
6110 /*!
6111  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6112  * out of the cell. 
6113  *  \throw If \a this->getMeshDimension() != 3.
6114  *  \throw If \a this->getSpaceDimension() != 3.
6115  *  \throw If the coordinates array is not set.
6116  *  \throw If the nodal connectivity of cells is not defined.
6117  *  \throw If the reparation fails.
6118  *
6119  *  \if ENABLE_EXAMPLES
6120  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6121  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6122  *  \endif
6123  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6124  */
6125 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6126 {
6127   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6128     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6129   int nbOfCells=getNumberOfCells();
6130   int *conn=_nodal_connec->getPointer();
6131   const int *connI=_nodal_connec_index->getConstPointer();
6132   const double *coordsPtr=_coords->getConstPointer();
6133   for(int i=0;i<nbOfCells;i++)
6134     {
6135       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6136       if(type==INTERP_KERNEL::NORM_POLYHED)
6137         {
6138           try
6139           {
6140               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6141                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6142           }
6143           catch(INTERP_KERNEL::Exception& e)
6144           {
6145               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6146               throw INTERP_KERNEL::Exception(oss.str().c_str());
6147           }
6148         }
6149     }
6150   updateTime();
6151 }
6152
6153 /*!
6154  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6155  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6156  * according to which the first facet of the cell should be oriented to have the normal vector
6157  * pointing out of cell.
6158  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6159  *         cells. The caller is to delete this array using decrRef() as it is no more
6160  *         needed. 
6161  *  \throw If \a this->getMeshDimension() != 3.
6162  *  \throw If \a this->getSpaceDimension() != 3.
6163  *  \throw If the coordinates array is not set.
6164  *  \throw If the nodal connectivity of cells is not defined.
6165  *
6166  *  \if ENABLE_EXAMPLES
6167  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6168  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6169  *  \endif
6170  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6171  */
6172 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6173 {
6174   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6175   if(getMeshDimension()!=3)
6176     throw INTERP_KERNEL::Exception(msg);
6177   int spaceDim=getSpaceDimension();
6178   if(spaceDim!=3)
6179     throw INTERP_KERNEL::Exception(msg);
6180   //
6181   int nbOfCells=getNumberOfCells();
6182   int *conn=_nodal_connec->getPointer();
6183   const int *connI=_nodal_connec_index->getConstPointer();
6184   const double *coo=getCoords()->getConstPointer();
6185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6186   for(int i=0;i<nbOfCells;i++)
6187     {
6188       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6189       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6190         {
6191           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6192             {
6193               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6194               cells->pushBackSilent(i);
6195             }
6196         }
6197     }
6198   return cells.retn();
6199 }
6200
6201 /*!
6202  * This method is a faster method to correct orientation of all 3D cells in \a this.
6203  * 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.
6204  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6205  * 
6206  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6207  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6208  */
6209 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6210 {
6211   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6212     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6213   int nbOfCells=getNumberOfCells();
6214   int *conn=_nodal_connec->getPointer();
6215   const int *connI=_nodal_connec_index->getConstPointer();
6216   const double *coordsPtr=_coords->getConstPointer();
6217   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6218   for(int i=0;i<nbOfCells;i++)
6219     {
6220       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6221       switch(type)
6222       {
6223         case INTERP_KERNEL::NORM_TETRA4:
6224           {
6225             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6226               {
6227                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6228                 ret->pushBackSilent(i);
6229               }
6230             break;
6231           }
6232         case INTERP_KERNEL::NORM_PYRA5:
6233           {
6234             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6235               {
6236                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6237                 ret->pushBackSilent(i);
6238               }
6239             break;
6240           }
6241         case INTERP_KERNEL::NORM_PENTA6:
6242         case INTERP_KERNEL::NORM_HEXA8:
6243         case INTERP_KERNEL::NORM_HEXGP12:
6244           {
6245             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6246               {
6247                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6248                 ret->pushBackSilent(i);
6249               }
6250             break;
6251           }
6252         case INTERP_KERNEL::NORM_POLYHED:
6253           {
6254             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6255               {
6256                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6257                 ret->pushBackSilent(i);
6258               }
6259             break;
6260           }
6261         default:
6262           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 !");
6263       }
6264     }
6265   updateTime();
6266   return ret.retn();
6267 }
6268
6269 /*!
6270  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6271  * If it is not the case an exception will be thrown.
6272  * This method is fast because the first cell of \a this is used to compute the plane.
6273  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6274  * \param pos output of size at least 3 used to store a point owned of searched plane.
6275  */
6276 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6277 {
6278   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6279     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6280   const int *conn=_nodal_connec->getConstPointer();
6281   const int *connI=_nodal_connec_index->getConstPointer();
6282   const double *coordsPtr=_coords->getConstPointer();
6283   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6284   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6285 }
6286
6287 /*!
6288  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6289  * cells. Currently cells of the following types are treated:
6290  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6291  * For a cell of other type an exception is thrown.
6292  * Space dimension of a 2D mesh can be either 2 or 3.
6293  * The Edge Ratio of a cell \f$t\f$ is: 
6294  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6295  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6296  *  the smallest edge lengths of \f$t\f$.
6297  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6298  *          cells and one time, lying on \a this mesh. The caller is to delete this
6299  *          field using decrRef() as it is no more needed. 
6300  *  \throw If the coordinates array is not set.
6301  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6302  *  \throw If the connectivity data array has more than one component.
6303  *  \throw If the connectivity data array has a named component.
6304  *  \throw If the connectivity index data array has more than one component.
6305  *  \throw If the connectivity index data array has a named component.
6306  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6307  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6308  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6309  */
6310 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6311 {
6312   checkCoherency();
6313   int spaceDim=getSpaceDimension();
6314   int meshDim=getMeshDimension();
6315   if(spaceDim!=2 && spaceDim!=3)
6316     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6317   if(meshDim!=2 && meshDim!=3)
6318     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6319   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6320   ret->setMesh(this);
6321   int nbOfCells=getNumberOfCells();
6322   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6323   arr->alloc(nbOfCells,1);
6324   double *pt=arr->getPointer();
6325   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6326   const int *conn=_nodal_connec->getConstPointer();
6327   const int *connI=_nodal_connec_index->getConstPointer();
6328   const double *coo=_coords->getConstPointer();
6329   double tmp[12];
6330   for(int i=0;i<nbOfCells;i++,pt++)
6331     {
6332       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6333       switch(t)
6334       {
6335         case INTERP_KERNEL::NORM_TRI3:
6336           {
6337             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6338             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6339             break;
6340           }
6341         case INTERP_KERNEL::NORM_QUAD4:
6342           {
6343             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6344             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6345             break;
6346           }
6347         case INTERP_KERNEL::NORM_TETRA4:
6348           {
6349             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6350             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6351             break;
6352           }
6353         default:
6354           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6355       }
6356       conn+=connI[i+1]-connI[i];
6357     }
6358   ret->setName("EdgeRatio");
6359   ret->synchronizeTimeWithSupport();
6360   return ret.retn();
6361 }
6362
6363 /*!
6364  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6365  * cells. Currently cells of the following types are treated:
6366  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6367  * For a cell of other type an exception is thrown.
6368  * Space dimension of a 2D mesh can be either 2 or 3.
6369  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6370  *          cells and one time, lying on \a this mesh. The caller is to delete this
6371  *          field using decrRef() as it is no more needed. 
6372  *  \throw If the coordinates array is not set.
6373  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6374  *  \throw If the connectivity data array has more than one component.
6375  *  \throw If the connectivity data array has a named component.
6376  *  \throw If the connectivity index data array has more than one component.
6377  *  \throw If the connectivity index data array has a named component.
6378  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6379  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6380  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6381  */
6382 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6383 {
6384   checkCoherency();
6385   int spaceDim=getSpaceDimension();
6386   int meshDim=getMeshDimension();
6387   if(spaceDim!=2 && spaceDim!=3)
6388     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6389   if(meshDim!=2 && meshDim!=3)
6390     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6391   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6392   ret->setMesh(this);
6393   int nbOfCells=getNumberOfCells();
6394   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6395   arr->alloc(nbOfCells,1);
6396   double *pt=arr->getPointer();
6397   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6398   const int *conn=_nodal_connec->getConstPointer();
6399   const int *connI=_nodal_connec_index->getConstPointer();
6400   const double *coo=_coords->getConstPointer();
6401   double tmp[12];
6402   for(int i=0;i<nbOfCells;i++,pt++)
6403     {
6404       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6405       switch(t)
6406       {
6407         case INTERP_KERNEL::NORM_TRI3:
6408           {
6409             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6410             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6411             break;
6412           }
6413         case INTERP_KERNEL::NORM_QUAD4:
6414           {
6415             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6416             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6417             break;
6418           }
6419         case INTERP_KERNEL::NORM_TETRA4:
6420           {
6421             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6422             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6423             break;
6424           }
6425         default:
6426           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6427       }
6428       conn+=connI[i+1]-connI[i];
6429     }
6430   ret->setName("AspectRatio");
6431   ret->synchronizeTimeWithSupport();
6432   return ret.retn();
6433 }
6434
6435 /*!
6436  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6437  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6438  * treated: INTERP_KERNEL::NORM_QUAD4.
6439  * For a cell of other type an exception is thrown.
6440  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6441  *          cells and one time, lying on \a this mesh. The caller is to delete this
6442  *          field using decrRef() as it is no more needed. 
6443  *  \throw If the coordinates array is not set.
6444  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6445  *  \throw If the connectivity data array has more than one component.
6446  *  \throw If the connectivity data array has a named component.
6447  *  \throw If the connectivity index data array has more than one component.
6448  *  \throw If the connectivity index data array has a named component.
6449  *  \throw If \a this->getMeshDimension() != 2.
6450  *  \throw If \a this->getSpaceDimension() != 3.
6451  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6452  */
6453 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6454 {
6455   checkCoherency();
6456   int spaceDim=getSpaceDimension();
6457   int meshDim=getMeshDimension();
6458   if(spaceDim!=3)
6459     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6460   if(meshDim!=2)
6461     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6462   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6463   ret->setMesh(this);
6464   int nbOfCells=getNumberOfCells();
6465   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6466   arr->alloc(nbOfCells,1);
6467   double *pt=arr->getPointer();
6468   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6469   const int *conn=_nodal_connec->getConstPointer();
6470   const int *connI=_nodal_connec_index->getConstPointer();
6471   const double *coo=_coords->getConstPointer();
6472   double tmp[12];
6473   for(int i=0;i<nbOfCells;i++,pt++)
6474     {
6475       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6476       switch(t)
6477       {
6478         case INTERP_KERNEL::NORM_QUAD4:
6479           {
6480             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6481             *pt=INTERP_KERNEL::quadWarp(tmp);
6482             break;
6483           }
6484         default:
6485           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6486       }
6487       conn+=connI[i+1]-connI[i];
6488     }
6489   ret->setName("Warp");
6490   ret->synchronizeTimeWithSupport();
6491   return ret.retn();
6492 }
6493
6494
6495 /*!
6496  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6497  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6498  * treated: INTERP_KERNEL::NORM_QUAD4.
6499  * For a cell of other type an exception is thrown.
6500  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6501  *          cells and one time, lying on \a this mesh. The caller is to delete this
6502  *          field using decrRef() as it is no more needed. 
6503  *  \throw If the coordinates array is not set.
6504  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6505  *  \throw If the connectivity data array has more than one component.
6506  *  \throw If the connectivity data array has a named component.
6507  *  \throw If the connectivity index data array has more than one component.
6508  *  \throw If the connectivity index data array has a named component.
6509  *  \throw If \a this->getMeshDimension() != 2.
6510  *  \throw If \a this->getSpaceDimension() != 3.
6511  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6512  */
6513 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6514 {
6515   checkCoherency();
6516   int spaceDim=getSpaceDimension();
6517   int meshDim=getMeshDimension();
6518   if(spaceDim!=3)
6519     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6520   if(meshDim!=2)
6521     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6522   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6523   ret->setMesh(this);
6524   int nbOfCells=getNumberOfCells();
6525   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6526   arr->alloc(nbOfCells,1);
6527   double *pt=arr->getPointer();
6528   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6529   const int *conn=_nodal_connec->getConstPointer();
6530   const int *connI=_nodal_connec_index->getConstPointer();
6531   const double *coo=_coords->getConstPointer();
6532   double tmp[12];
6533   for(int i=0;i<nbOfCells;i++,pt++)
6534     {
6535       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6536       switch(t)
6537       {
6538         case INTERP_KERNEL::NORM_QUAD4:
6539           {
6540             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6541             *pt=INTERP_KERNEL::quadSkew(tmp);
6542             break;
6543           }
6544         default:
6545           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6546       }
6547       conn+=connI[i+1]-connI[i];
6548     }
6549   ret->setName("Skew");
6550   ret->synchronizeTimeWithSupport();
6551   return ret.retn();
6552 }
6553
6554 /*!
6555  * 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.
6556  *
6557  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6558  *
6559  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6560  */
6561 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6562 {
6563   checkCoherency();
6564   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6565   ret->setMesh(this);
6566   std::set<INTERP_KERNEL::NormalizedCellType> types;
6567   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6568   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6569   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6570   arr->alloc(nbCells,1);
6571   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6572     {
6573       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6574       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6575       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6576     }
6577   ret->setArray(arr);
6578   ret->setName("Diameter");
6579   return ret.retn();
6580 }
6581
6582 /*!
6583  * This method aggregate the bbox of each cell and put it into bbox parameter.
6584  * 
6585  * \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)
6586  *                         For all other cases this input parameter is ignored.
6587  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6588  * 
6589  * \throw If \a this is not fully set (coordinates and connectivity).
6590  * \throw If a cell in \a this has no valid nodeId.
6591  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6592  */
6593 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6594 {
6595   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6596   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.
6597     return getBoundingBoxForBBTreeFast();
6598   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6599     {
6600       bool presenceOfQuadratic(false);
6601       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6602         {
6603           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6604           if(cm.isQuadratic())
6605             presenceOfQuadratic=true;
6606         }
6607       if(!presenceOfQuadratic)
6608         return getBoundingBoxForBBTreeFast();
6609       if(mDim==2 && sDim==2)
6610         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6611       else
6612         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6613     }
6614   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) !");
6615 }
6616
6617 /*!
6618  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6619  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6620  * 
6621  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6622  * 
6623  * \throw If \a this is not fully set (coordinates and connectivity).
6624  * \throw If a cell in \a this has no valid nodeId.
6625  */
6626 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6627 {
6628   checkFullyDefined();
6629   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6630   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6631   double *bbox(ret->getPointer());
6632   for(int i=0;i<nbOfCells*spaceDim;i++)
6633     {
6634       bbox[2*i]=std::numeric_limits<double>::max();
6635       bbox[2*i+1]=-std::numeric_limits<double>::max();
6636     }
6637   const double *coordsPtr(_coords->getConstPointer());
6638   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6639   for(int i=0;i<nbOfCells;i++)
6640     {
6641       int offset=connI[i]+1;
6642       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6643       for(int j=0;j<nbOfNodesForCell;j++)
6644         {
6645           int nodeId=conn[offset+j];
6646           if(nodeId>=0 && nodeId<nbOfNodes)
6647             {
6648               for(int k=0;k<spaceDim;k++)
6649                 {
6650                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6651                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6652                 }
6653               kk++;
6654             }
6655         }
6656       if(kk==0)
6657         {
6658           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6659           throw INTERP_KERNEL::Exception(oss.str().c_str());
6660         }
6661     }
6662   return ret.retn();
6663 }
6664
6665 /*!
6666  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6667  * useful for 2D meshes having quadratic cells
6668  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6669  * the two extremities of the arc of circle).
6670  * 
6671  * \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)
6672  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6673  * \throw If \a this is not fully defined.
6674  * \throw If \a this is not a mesh with meshDimension equal to 2.
6675  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6676  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6677  */
6678 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6679 {
6680   checkFullyDefined();
6681   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6682   if(spaceDim!=2 || mDim!=2)
6683     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!");
6684   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6685   double *bbox(ret->getPointer());
6686   const double *coords(_coords->getConstPointer());
6687   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6688   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6689     {
6690       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6691       int sz(connI[1]-connI[0]-1);
6692       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6693       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6694       INTERP_KERNEL::QuadraticPolygon *pol(0);
6695       for(int j=0;j<sz;j++)
6696         {
6697           int nodeId(conn[*connI+1+j]);
6698           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6699         }
6700       if(!cm.isQuadratic())
6701         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6702       else
6703         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6704       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6705       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6706     }
6707   return ret.retn();
6708 }
6709
6710 /*!
6711  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6712  * useful for 2D meshes having quadratic cells
6713  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6714  * the two extremities of the arc of circle).
6715  * 
6716  * \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)
6717  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6718  * \throw If \a this is not fully defined.
6719  * \throw If \a this is not a mesh with meshDimension equal to 1.
6720  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6721  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6722  */
6723 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6724 {
6725   checkFullyDefined();
6726   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6727   if(spaceDim!=2 || mDim!=1)
6728     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!");
6729   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6730   double *bbox(ret->getPointer());
6731   const double *coords(_coords->getConstPointer());
6732   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6733   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6734     {
6735       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6736       int sz(connI[1]-connI[0]-1);
6737       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6738       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6739       INTERP_KERNEL::Edge *edge(0);
6740       for(int j=0;j<sz;j++)
6741         {
6742           int nodeId(conn[*connI+1+j]);
6743           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6744         }
6745       if(!cm.isQuadratic())
6746         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6747       else
6748         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6749       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6750       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6751     }
6752   return ret.retn();
6753 }
6754
6755 /// @cond INTERNAL
6756
6757 namespace ParaMEDMEMImpl
6758 {
6759   class ConnReader
6760   {
6761   public:
6762     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6763     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6764   private:
6765     const int *_conn;
6766     int _val;
6767   };
6768
6769   class ConnReader2
6770   {
6771   public:
6772     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6773     bool operator() (const int& pos) { return _conn[pos]==_val; }
6774   private:
6775     const int *_conn;
6776     int _val;
6777   };
6778 }
6779
6780 /// @endcond
6781
6782 /*!
6783  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6784  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6785  * \a this is composed in cell types.
6786  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6787  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6788  * This parameter is kept only for compatibility with other methode listed above.
6789  */
6790 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6791 {
6792   checkConnectivityFullyDefined();
6793   const int *conn=_nodal_connec->getConstPointer();
6794   const int *connI=_nodal_connec_index->getConstPointer();
6795   const int *work=connI;
6796   int nbOfCells=getNumberOfCells();
6797   std::size_t n=getAllGeoTypes().size();
6798   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6799   std::set<INTERP_KERNEL::NormalizedCellType> types;
6800   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6801     {
6802       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6803       if(types.find(typ)!=types.end())
6804         {
6805           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6806           oss << " is not contiguous !";
6807           throw INTERP_KERNEL::Exception(oss.str().c_str());
6808         }
6809       types.insert(typ);
6810       ret[3*i]=typ;
6811       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6812       ret[3*i+1]=(int)std::distance(work,work2);
6813       work=work2;
6814     }
6815   return ret;
6816 }
6817
6818 /*!
6819  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6820  * only for types cell, type node is not managed.
6821  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6822  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6823  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6824  * If 2 or more same geometric type is in \a code and exception is thrown too.
6825  *
6826  * This method firstly checks
6827  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6828  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6829  * an exception is thrown too.
6830  * 
6831  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6832  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6833  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6834  */
6835 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6836 {
6837   if(code.empty())
6838     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6839   std::size_t sz=code.size();
6840   std::size_t n=sz/3;
6841   if(sz%3!=0)
6842     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6843   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6844   int nb=0;
6845   bool isNoPflUsed=true;
6846   for(std::size_t i=0;i<n;i++)
6847     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6848       {
6849         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6850         nb+=code[3*i+1];
6851         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6852           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6853         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6854       }
6855   if(types.size()!=n)
6856     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6857   if(isNoPflUsed)
6858     {
6859       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6860         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6861       if(types.size()==_types.size())
6862         return 0;
6863     }
6864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6865   ret->alloc(nb,1);
6866   int *retPtr=ret->getPointer();
6867   const int *connI=_nodal_connec_index->getConstPointer();
6868   const int *conn=_nodal_connec->getConstPointer();
6869   int nbOfCells=getNumberOfCells();
6870   const int *i=connI;
6871   int kk=0;
6872   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6873     {
6874       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6875       int offset=(int)std::distance(connI,i);
6876       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6877       int nbOfCellsOfCurType=(int)std::distance(i,j);
6878       if(code[3*kk+2]==-1)
6879         for(int k=0;k<nbOfCellsOfCurType;k++)
6880           *retPtr++=k+offset;
6881       else
6882         {
6883           int idInIdsPerType=code[3*kk+2];
6884           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6885             {
6886               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6887               if(zePfl)
6888                 {
6889                   zePfl->checkAllocated();
6890                   if(zePfl->getNumberOfComponents()==1)
6891                     {
6892                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6893                         {
6894                           if(*k>=0 && *k<nbOfCellsOfCurType)
6895                             *retPtr=(*k)+offset;
6896                           else
6897                             {
6898                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6899                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6900                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6901                             }
6902                         }
6903                     }
6904                   else
6905                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6906                 }
6907               else
6908                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6909             }
6910           else
6911             {
6912               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6913               oss << " should be in [0," << idsPerType.size() << ") !";
6914               throw INTERP_KERNEL::Exception(oss.str().c_str());
6915             }
6916         }
6917       i=j;
6918     }
6919   return ret.retn();
6920 }
6921
6922 /*!
6923  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6924  * 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.
6925  * 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.
6926  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6927  * 
6928  * \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.
6929  * \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,
6930  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6931  * \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.
6932  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6933  * \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
6934  */
6935 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6936 {
6937   if(!profile)
6938     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6939   if(profile->getNumberOfComponents()!=1)
6940     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6941   checkConnectivityFullyDefined();
6942   const int *conn=_nodal_connec->getConstPointer();
6943   const int *connI=_nodal_connec_index->getConstPointer();
6944   int nbOfCells=getNumberOfCells();
6945   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6946   std::vector<int> typeRangeVals(1);
6947   for(const int *i=connI;i!=connI+nbOfCells;)
6948     {
6949       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6950       if(std::find(types.begin(),types.end(),curType)!=types.end())
6951         {
6952           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6953         }
6954       types.push_back(curType);
6955       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6956       typeRangeVals.push_back((int)std::distance(connI,i));
6957     }
6958   //
6959   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6960   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6961   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6963   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6964   //
6965   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6966   code.resize(3*nbOfCastsFinal);
6967   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6968   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6969   for(int i=0;i<nbOfCastsFinal;i++)
6970     {
6971       int castId=castsPresent->getIJ(i,0);
6972       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6973       idsInPflPerType2.push_back(tmp3);
6974       code[3*i]=(int)types[castId];
6975       code[3*i+1]=tmp3->getNumberOfTuples();
6976       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6977       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6978         {
6979           tmp4->copyStringInfoFrom(*profile);
6980           idsPerType2.push_back(tmp4);
6981           code[3*i+2]=(int)idsPerType2.size()-1;
6982         }
6983       else
6984         {
6985           code[3*i+2]=-1;
6986         }
6987     }
6988   std::size_t sz2=idsInPflPerType2.size();
6989   idsInPflPerType.resize(sz2);
6990   for(std::size_t i=0;i<sz2;i++)
6991     {
6992       DataArrayInt *locDa=idsInPflPerType2[i];
6993       locDa->incrRef();
6994       idsInPflPerType[i]=locDa;
6995     }
6996   std::size_t sz=idsPerType2.size();
6997   idsPerType.resize(sz);
6998   for(std::size_t i=0;i<sz;i++)
6999     {
7000       DataArrayInt *locDa=idsPerType2[i];
7001       locDa->incrRef();
7002       idsPerType[i]=locDa;
7003     }
7004 }
7005
7006 /*!
7007  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7008  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7009  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7010  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as ParaMEDMEM::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered.
7011  */
7012 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7013 {
7014   checkFullyDefined();
7015   nM1LevMesh->checkFullyDefined();
7016   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7017     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7018   if(_coords!=nM1LevMesh->getCoords())
7019     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7020   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7021   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7022   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7023   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7024   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7025   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7026   tmp->setConnectivity(tmp0,tmp1);
7027   tmp->renumberCells(ret0->getConstPointer(),false);
7028   revDesc=tmp->getNodalConnectivity();
7029   revDescIndx=tmp->getNodalConnectivityIndex();
7030   DataArrayInt *ret=0;
7031   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7032     {
7033       int tmp2;
7034       ret->getMaxValue(tmp2);
7035       ret->decrRef();
7036       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7037       throw INTERP_KERNEL::Exception(oss.str().c_str());
7038     }
7039   nM1LevMeshIds=ret;
7040   //
7041   revDesc->incrRef();
7042   revDescIndx->incrRef();
7043   ret1->incrRef();
7044   ret0->incrRef();
7045   meshnM1Old2New=ret0;
7046   return ret1;
7047 }
7048
7049 /*!
7050  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7051  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7052  * in "Old to New" mode.
7053  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7054  *          this array using decrRef() as it is no more needed.
7055  *  \throw If the nodal connectivity of cells is not defined.
7056  */
7057 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7058 {
7059   checkConnectivityFullyDefined();
7060   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7061   renumberCells(ret->getConstPointer(),false);
7062   return ret.retn();
7063 }
7064
7065 /*!
7066  * This methods checks that cells are sorted by their types.
7067  * This method makes asumption (no check) that connectivity is correctly set before calling.
7068  */
7069 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7070 {
7071   checkFullyDefined();
7072   const int *conn=_nodal_connec->getConstPointer();
7073   const int *connI=_nodal_connec_index->getConstPointer();
7074   int nbOfCells=getNumberOfCells();
7075   std::set<INTERP_KERNEL::NormalizedCellType> types;
7076   for(const int *i=connI;i!=connI+nbOfCells;)
7077     {
7078       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7079       if(types.find(curType)!=types.end())
7080         return false;
7081       types.insert(curType);
7082       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7083     }
7084   return true;
7085 }
7086
7087 /*!
7088  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7089  * The geometric type order is specified by MED file.
7090  * 
7091  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7092  */
7093 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7094 {
7095   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7096 }
7097
7098 /*!
7099  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7100  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7101  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7102  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7103  */
7104 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7105 {
7106   checkFullyDefined();
7107   const int *conn=_nodal_connec->getConstPointer();
7108   const int *connI=_nodal_connec_index->getConstPointer();
7109   int nbOfCells=getNumberOfCells();
7110   if(nbOfCells==0)
7111     return true;
7112   int lastPos=-1;
7113   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7114   for(const int *i=connI;i!=connI+nbOfCells;)
7115     {
7116       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7117       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7118       if(isTypeExists!=orderEnd)
7119         {
7120           int pos=(int)std::distance(orderBg,isTypeExists);
7121           if(pos<=lastPos)
7122             return false;
7123           lastPos=pos;
7124           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7125         }
7126       else
7127         {
7128           if(sg.find(curType)==sg.end())
7129             {
7130               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7131               sg.insert(curType);
7132             }
7133           else
7134             return false;
7135         }
7136     }
7137   return true;
7138 }
7139
7140 /*!
7141  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7142  * 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
7143  * 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'.
7144  */
7145 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7146 {
7147   checkConnectivityFullyDefined();
7148   int nbOfCells=getNumberOfCells();
7149   const int *conn=_nodal_connec->getConstPointer();
7150   const int *connI=_nodal_connec_index->getConstPointer();
7151   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7152   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7153   tmpa->alloc(nbOfCells,1);
7154   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7155   tmpb->fillWithZero();
7156   int *tmp=tmpa->getPointer();
7157   int *tmp2=tmpb->getPointer();
7158   for(const int *i=connI;i!=connI+nbOfCells;i++)
7159     {
7160       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7161       if(where!=orderEnd)
7162         {
7163           int pos=(int)std::distance(orderBg,where);
7164           tmp2[pos]++;
7165           tmp[std::distance(connI,i)]=pos;
7166         }
7167       else
7168         {
7169           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7170           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7171           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7172           throw INTERP_KERNEL::Exception(oss.str().c_str());
7173         }
7174     }
7175   nbPerType=tmpb.retn();
7176   return tmpa.retn();
7177 }
7178
7179 /*!
7180  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7181  *
7182  * \return a new object containing the old to new correspondance.
7183  *
7184  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7185  */
7186 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7187 {
7188   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7189 }
7190
7191 /*!
7192  * 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.
7193  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7194  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7195  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7196  */
7197 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7198 {
7199   DataArrayInt *nbPerType=0;
7200   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7201   nbPerType->decrRef();
7202   return tmpa->buildPermArrPerLevel();
7203 }
7204
7205 /*!
7206  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7207  * The number of cells remains unchanged after the call of this method.
7208  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7209  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7210  *
7211  * \return the array giving the correspondance old to new.
7212  */
7213 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7214 {
7215   checkFullyDefined();
7216   computeTypes();
7217   const int *conn=_nodal_connec->getConstPointer();
7218   const int *connI=_nodal_connec_index->getConstPointer();
7219   int nbOfCells=getNumberOfCells();
7220   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7221   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7222     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7223       {
7224         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7225         types.push_back(curType);
7226         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7227       }
7228   DataArrayInt *ret=DataArrayInt::New();
7229   ret->alloc(nbOfCells,1);
7230   int *retPtr=ret->getPointer();
7231   std::fill(retPtr,retPtr+nbOfCells,-1);
7232   int newCellId=0;
7233   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7234     {
7235       for(const int *i=connI;i!=connI+nbOfCells;i++)
7236         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7237           retPtr[std::distance(connI,i)]=newCellId++;
7238     }
7239   renumberCells(retPtr,false);
7240   return ret;
7241 }
7242
7243 /*!
7244  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7245  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7246  * This method makes asumption that connectivity is correctly set before calling.
7247  */
7248 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7249 {
7250   checkConnectivityFullyDefined();
7251   const int *conn=_nodal_connec->getConstPointer();
7252   const int *connI=_nodal_connec_index->getConstPointer();
7253   int nbOfCells=getNumberOfCells();
7254   std::vector<MEDCouplingUMesh *> ret;
7255   for(const int *i=connI;i!=connI+nbOfCells;)
7256     {
7257       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7258       int beginCellId=(int)std::distance(connI,i);
7259       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7260       int endCellId=(int)std::distance(connI,i);
7261       int sz=endCellId-beginCellId;
7262       int *cells=new int[sz];
7263       for(int j=0;j<sz;j++)
7264         cells[j]=beginCellId+j;
7265       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7266       delete [] cells;
7267       ret.push_back(m);
7268     }
7269   return ret;
7270 }
7271
7272 /*!
7273  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7274  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7275  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7276  *
7277  * \return a newly allocated instance, that the caller must manage.
7278  * \throw If \a this contains more than one geometric type.
7279  * \throw If the nodal connectivity of \a this is not fully defined.
7280  * \throw If the internal data is not coherent.
7281  */
7282 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7283 {
7284   checkConnectivityFullyDefined();
7285   if(_types.size()!=1)
7286     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7287   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7288   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7289   ret->setCoords(getCoords());
7290   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7291   if(retC)
7292     {
7293       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7294       retC->setNodalConnectivity(c);
7295     }
7296   else
7297     {
7298       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7299       if(!retD)
7300         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7301       DataArrayInt *c=0,*ci=0;
7302       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7303       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7304       retD->setNodalConnectivity(cs,cis);
7305     }
7306   return ret.retn();
7307 }
7308
7309 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7310 {
7311   checkConnectivityFullyDefined();
7312   if(_types.size()!=1)
7313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7314   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7315   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7316   if(cm.isDynamic())
7317     {
7318       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7319       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7320       throw INTERP_KERNEL::Exception(oss.str().c_str());
7321     }
7322   int nbCells=getNumberOfCells();
7323   int typi=(int)typ;
7324   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7325   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7326   int *outPtr=connOut->getPointer();
7327   const int *conn=_nodal_connec->begin();
7328   const int *connI=_nodal_connec_index->begin();
7329   nbNodesPerCell++;
7330   for(int i=0;i<nbCells;i++,connI++)
7331     {
7332       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7333         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7334       else
7335         {
7336           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 << ") !";
7337           throw INTERP_KERNEL::Exception(oss.str().c_str());
7338         }
7339     }
7340   return connOut.retn();
7341 }
7342
7343 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7344 {
7345   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7346   checkConnectivityFullyDefined();
7347   if(_types.size()!=1)
7348     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7349   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7350   if(lgth<nbCells)
7351     throw INTERP_KERNEL::Exception(msg0);
7352   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7353   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7354   int *cp(c->getPointer()),*cip(ci->getPointer());
7355   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7356   cip[0]=0;
7357   for(int i=0;i<nbCells;i++,cip++,incip++)
7358     {
7359       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7360       int delta(stop-strt);
7361       if(delta>=1)
7362         {
7363           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7364             cp=std::copy(incp+strt,incp+stop,cp);
7365           else
7366             throw INTERP_KERNEL::Exception(msg0);
7367         }
7368       else
7369         throw INTERP_KERNEL::Exception(msg0);
7370       cip[1]=cip[0]+delta;
7371     }
7372   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7373 }
7374
7375 /*!
7376  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7377  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7378  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7379  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7380  * are not used here to avoid the build of big permutation array.
7381  *
7382  * \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
7383  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7384  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7385  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7386  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7387  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7388  * \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
7389  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7390  */
7391 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7392                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7393                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7394 {
7395   std::vector<const MEDCouplingUMesh *> ms2;
7396   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7397     if(*it)
7398       {
7399         (*it)->checkConnectivityFullyDefined();
7400         ms2.push_back(*it);
7401       }
7402   if(ms2.empty())
7403     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7404   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7405   int meshDim=ms2[0]->getMeshDimension();
7406   std::vector<const MEDCouplingUMesh *> m1ssm;
7407   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7408   //
7409   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7410   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7411   int fake=0,rk=0;
7412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7413   ret1->alloc(0,1); ret2->alloc(0,1);
7414   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7415     {
7416       if(meshDim!=(*it)->getMeshDimension())
7417         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7418       if(refCoo!=(*it)->getCoords())
7419         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7420       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7421       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7422       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7423       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7424         {
7425           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7426           m1ssmSingleAuto.push_back(singleCell);
7427           m1ssmSingle.push_back(singleCell);
7428           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7429         }
7430     }
7431   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7433   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7434   for(std::size_t i=0;i<m1ssm.size();i++)
7435     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7436   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7437   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7438   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7439   return ret0.retn();
7440 }
7441
7442 /*!
7443  * This method returns a newly created DataArrayInt instance.
7444  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7445  */
7446 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7447 {
7448   checkFullyDefined();
7449   const int *conn=_nodal_connec->getConstPointer();
7450   const int *connIndex=_nodal_connec_index->getConstPointer();
7451   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7452   for(const int *w=begin;w!=end;w++)
7453     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7454       ret->pushBackSilent(*w);
7455   return ret.retn();
7456 }
7457
7458 /*!
7459  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7460  * are in [0:getNumberOfCells())
7461  */
7462 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7463 {
7464   checkFullyDefined();
7465   const int *conn=_nodal_connec->getConstPointer();
7466   const int *connI=_nodal_connec_index->getConstPointer();
7467   int nbOfCells=getNumberOfCells();
7468   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7469   int *tmp=new int[nbOfCells];
7470   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7471     {
7472       int j=0;
7473       for(const int *i=connI;i!=connI+nbOfCells;i++)
7474         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7475           tmp[std::distance(connI,i)]=j++;
7476     }
7477   DataArrayInt *ret=DataArrayInt::New();
7478   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7479   ret->copyStringInfoFrom(*da);
7480   int *retPtr=ret->getPointer();
7481   const int *daPtr=da->getConstPointer();
7482   int nbOfElems=da->getNbOfElems();
7483   for(int k=0;k<nbOfElems;k++)
7484     retPtr[k]=tmp[daPtr[k]];
7485   delete [] tmp;
7486   return ret;
7487 }
7488
7489 /*!
7490  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7491  * This method \b works \b for mesh sorted by type.
7492  * cells whose ids is in 'idsPerGeoType' array.
7493  * This method conserves coords and name of mesh.
7494  */
7495 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7496 {
7497   std::vector<int> code=getDistributionOfTypes();
7498   std::size_t nOfTypesInThis=code.size()/3;
7499   int sz=0,szOfType=0;
7500   for(std::size_t i=0;i<nOfTypesInThis;i++)
7501     {
7502       if(code[3*i]!=type)
7503         sz+=code[3*i+1];
7504       else
7505         szOfType=code[3*i+1];
7506     }
7507   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7508     if(*work<0 || *work>=szOfType)
7509       {
7510         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7511         oss << ". It should be in [0," << szOfType << ") !";
7512         throw INTERP_KERNEL::Exception(oss.str().c_str());
7513       }
7514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7515   int *idsPtr=idsTokeep->getPointer();
7516   int offset=0;
7517   for(std::size_t i=0;i<nOfTypesInThis;i++)
7518     {
7519       if(code[3*i]!=type)
7520         for(int j=0;j<code[3*i+1];j++)
7521           *idsPtr++=offset+j;
7522       else
7523         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7524       offset+=code[3*i+1];
7525     }
7526   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7527   ret->copyTinyInfoFrom(this);
7528   return ret.retn();
7529 }
7530
7531 /*!
7532  * This method returns a vector of size 'this->getNumberOfCells()'.
7533  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7534  */
7535 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7536 {
7537   int ncell=getNumberOfCells();
7538   std::vector<bool> ret(ncell);
7539   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7540   const int *c=getNodalConnectivity()->getConstPointer();
7541   for(int i=0;i<ncell;i++)
7542     {
7543       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7544       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7545       ret[i]=cm.isQuadratic();
7546     }
7547   return ret;
7548 }
7549
7550 /*!
7551  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7552  */
7553 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7554 {
7555   if(other->getType()!=UNSTRUCTURED)
7556     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7557   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7558   return MergeUMeshes(this,otherC);
7559 }
7560
7561 /*!
7562  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7563  * computed by averaging coordinates of cell nodes, so this method is not a right
7564  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7565  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7566  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7567  *          components. The caller is to delete this array using decrRef() as it is
7568  *          no more needed.
7569  *  \throw If the coordinates array is not set.
7570  *  \throw If the nodal connectivity of cells is not defined.
7571  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7572  */
7573 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7574 {
7575   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7576   int spaceDim=getSpaceDimension();
7577   int nbOfCells=getNumberOfCells();
7578   ret->alloc(nbOfCells,spaceDim);
7579   ret->copyStringInfoFrom(*getCoords());
7580   double *ptToFill=ret->getPointer();
7581   const int *nodal=_nodal_connec->getConstPointer();
7582   const int *nodalI=_nodal_connec_index->getConstPointer();
7583   const double *coor=_coords->getConstPointer();
7584   for(int i=0;i<nbOfCells;i++)
7585     {
7586       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7587       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7588       ptToFill+=spaceDim;
7589     }
7590   return ret.retn();
7591 }
7592
7593 /*!
7594  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7595  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7596  * 
7597  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7598  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7599  * 
7600  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7601  * \throw If \a this is not fully defined (coordinates and connectivity)
7602  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7603  */
7604 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7605 {
7606   checkFullyDefined();
7607   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7608   int spaceDim=getSpaceDimension();
7609   int nbOfCells=getNumberOfCells();
7610   int nbOfNodes=getNumberOfNodes();
7611   ret->alloc(nbOfCells,spaceDim);
7612   double *ptToFill=ret->getPointer();
7613   const int *nodal=_nodal_connec->getConstPointer();
7614   const int *nodalI=_nodal_connec_index->getConstPointer();
7615   const double *coor=_coords->getConstPointer();
7616   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7617     {
7618       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7619       std::fill(ptToFill,ptToFill+spaceDim,0.);
7620       if(type!=INTERP_KERNEL::NORM_POLYHED)
7621         {
7622           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7623             {
7624               if(*conn>=0 && *conn<nbOfNodes)
7625                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7626               else
7627                 {
7628                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7629                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7630                 }
7631             }
7632           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7633           if(nbOfNodesInCell>0)
7634             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7635           else
7636             {
7637               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7638               throw INTERP_KERNEL::Exception(oss.str().c_str());
7639             }
7640         }
7641       else
7642         {
7643           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7644           s.erase(-1);
7645           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7646             {
7647               if(*it>=0 && *it<nbOfNodes)
7648                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7649               else
7650                 {
7651                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7652                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7653                 }
7654             }
7655           if(!s.empty())
7656             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7657           else
7658             {
7659               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7660               throw INTERP_KERNEL::Exception(oss.str().c_str());
7661             }
7662         }
7663     }
7664   return ret.retn();
7665 }
7666
7667 /*!
7668  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7669  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7670  * are specified via an array of cell ids. 
7671  *  \warning Validity of the specified cell ids is not checked! 
7672  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7673  *  \param [in] begin - an array of cell ids of interest.
7674  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7675  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7676  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7677  *          caller is to delete this array using decrRef() as it is no more needed. 
7678  *  \throw If the coordinates array is not set.
7679  *  \throw If the nodal connectivity of cells is not defined.
7680  *
7681  *  \if ENABLE_EXAMPLES
7682  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7683  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7684  *  \endif
7685  */
7686 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7687 {
7688   DataArrayDouble *ret=DataArrayDouble::New();
7689   int spaceDim=getSpaceDimension();
7690   int nbOfTuple=(int)std::distance(begin,end);
7691   ret->alloc(nbOfTuple,spaceDim);
7692   double *ptToFill=ret->getPointer();
7693   double *tmp=new double[spaceDim];
7694   const int *nodal=_nodal_connec->getConstPointer();
7695   const int *nodalI=_nodal_connec_index->getConstPointer();
7696   const double *coor=_coords->getConstPointer();
7697   for(const int *w=begin;w!=end;w++)
7698     {
7699       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7700       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7701       ptToFill+=spaceDim;
7702     }
7703   delete [] tmp;
7704   return ret;
7705 }
7706
7707 /*!
7708  * 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".
7709  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7710  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7711  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7712  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7713  * 
7714  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7715  * \throw If spaceDim!=3 or meshDim!=2.
7716  * \throw If connectivity of \a this is invalid.
7717  * \throw If connectivity of a cell in \a this points to an invalid node.
7718  */
7719 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7720 {
7721   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7722   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7723   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7724     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7725   ret->alloc(nbOfCells,4);
7726   double *retPtr(ret->getPointer());
7727   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7728   const double *coor(_coords->begin());
7729   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7730     {
7731       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7732       if(nodalI[1]-nodalI[0]>=3)
7733         {
7734           for(int j=0;j<3;j++)
7735             {
7736               int nodeId(nodal[nodalI[0]+1+j]);
7737               if(nodeId>=0 && nodeId<nbOfNodes)
7738                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7739               else
7740                 {
7741                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7742                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7743                 }
7744             }
7745         }
7746       else
7747         {
7748           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7749           throw INTERP_KERNEL::Exception(oss.str().c_str());
7750         }
7751       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7752       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7753     }
7754   return ret.retn();
7755 }
7756
7757 /*!
7758  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7759  * 
7760  */
7761 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7762 {
7763   if(!da)
7764     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7765   da->checkAllocated();
7766   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7767   ret->setCoords(da);
7768   int nbOfTuples=da->getNumberOfTuples();
7769   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7770   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7771   c->alloc(2*nbOfTuples,1);
7772   cI->alloc(nbOfTuples+1,1);
7773   int *cp=c->getPointer();
7774   int *cip=cI->getPointer();
7775   *cip++=0;
7776   for(int i=0;i<nbOfTuples;i++)
7777     {
7778       *cp++=INTERP_KERNEL::NORM_POINT1;
7779       *cp++=i;
7780       *cip++=2*(i+1);
7781     }
7782   ret->setConnectivity(c,cI,true);
7783   return ret.retn();
7784 }
7785 /*!
7786  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7787  * Cells and nodes of
7788  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7789  *  \param [in] mesh1 - the first mesh.
7790  *  \param [in] mesh2 - the second mesh.
7791  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7792  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7793  *          is no more needed.
7794  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7795  *  \throw If the coordinates array is not set in none of the meshes.
7796  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7797  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7798  */
7799 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7800 {
7801   std::vector<const MEDCouplingUMesh *> tmp(2);
7802   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7803   return MergeUMeshes(tmp);
7804 }
7805
7806 /*!
7807  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7808  * Cells and nodes of
7809  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7810  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7811  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7812  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7813  *          is no more needed.
7814  *  \throw If \a a.size() == 0.
7815  *  \throw If \a a[ *i* ] == NULL.
7816  *  \throw If the coordinates array is not set in none of the meshes.
7817  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7818  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7819  */
7820 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7821 {
7822   std::size_t sz=a.size();
7823   if(sz==0)
7824     return MergeUMeshesLL(a);
7825   for(std::size_t ii=0;ii<sz;ii++)
7826     if(!a[ii])
7827       {
7828         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7829         throw INTERP_KERNEL::Exception(oss.str().c_str());
7830       }
7831   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7832   std::vector< const MEDCouplingUMesh * > aa(sz);
7833   int spaceDim=-3;
7834   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7835     {
7836       const MEDCouplingUMesh *cur=a[i];
7837       const DataArrayDouble *coo=cur->getCoords();
7838       if(coo)
7839         spaceDim=coo->getNumberOfComponents();
7840     }
7841   if(spaceDim==-3)
7842     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7843   for(std::size_t i=0;i<sz;i++)
7844     {
7845       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7846       aa[i]=bb[i];
7847     }
7848   return MergeUMeshesLL(aa);
7849 }
7850
7851 /// @cond INTERNAL
7852
7853 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7854 {
7855   if(a.empty())
7856     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7857   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7858   int meshDim=(*it)->getMeshDimension();
7859   int nbOfCells=(*it)->getNumberOfCells();
7860   int meshLgth=(*it++)->getMeshLength();
7861   for(;it!=a.end();it++)
7862     {
7863       if(meshDim!=(*it)->getMeshDimension())
7864         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7865       nbOfCells+=(*it)->getNumberOfCells();
7866       meshLgth+=(*it)->getMeshLength();
7867     }
7868   std::vector<const MEDCouplingPointSet *> aps(a.size());
7869   std::copy(a.begin(),a.end(),aps.begin());
7870   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7871   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7872   ret->setCoords(pts);
7873   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7874   c->alloc(meshLgth,1);
7875   int *cPtr=c->getPointer();
7876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7877   cI->alloc(nbOfCells+1,1);
7878   int *cIPtr=cI->getPointer();
7879   *cIPtr++=0;
7880   int offset=0;
7881   int offset2=0;
7882   for(it=a.begin();it!=a.end();it++)
7883     {
7884       int curNbOfCell=(*it)->getNumberOfCells();
7885       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7886       const int *curC=(*it)->_nodal_connec->getConstPointer();
7887       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7888       for(int j=0;j<curNbOfCell;j++)
7889         {
7890           const int *src=curC+curCI[j];
7891           *cPtr++=*src++;
7892           for(;src!=curC+curCI[j+1];src++,cPtr++)
7893             {
7894               if(*src!=-1)
7895                 *cPtr=*src+offset2;
7896               else
7897                 *cPtr=-1;
7898             }
7899         }
7900       offset+=curCI[curNbOfCell];
7901       offset2+=(*it)->getNumberOfNodes();
7902     }
7903   //
7904   ret->setConnectivity(c,cI,true);
7905   return ret.retn();
7906 }
7907
7908 /// @endcond
7909
7910 /*!
7911  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7912  * dimension and sharing the node coordinates array.
7913  * All cells of the first mesh precede all cells of the second mesh
7914  * within the result mesh. 
7915  *  \param [in] mesh1 - the first mesh.
7916  *  \param [in] mesh2 - the second mesh.
7917  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7918  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7919  *          is no more needed.
7920  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7921  *  \throw If the meshes do not share the node coordinates array.
7922  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7923  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7924  */
7925 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7926 {
7927   std::vector<const MEDCouplingUMesh *> tmp(2);
7928   tmp[0]=mesh1; tmp[1]=mesh2;
7929   return MergeUMeshesOnSameCoords(tmp);
7930 }
7931
7932 /*!
7933  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7934  * dimension and sharing the node coordinates array.
7935  * All cells of the *i*-th mesh precede all cells of the
7936  * (*i*+1)-th mesh within the result mesh.
7937  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7938  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7939  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7940  *          is no more needed.
7941  *  \throw If \a a.size() == 0.
7942  *  \throw If \a a[ *i* ] == NULL.
7943  *  \throw If the meshes do not share the node coordinates array.
7944  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7945  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7946  */
7947 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7948 {
7949   if(meshes.empty())
7950     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7951   for(std::size_t ii=0;ii<meshes.size();ii++)
7952     if(!meshes[ii])
7953       {
7954         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7955         throw INTERP_KERNEL::Exception(oss.str().c_str());
7956       }
7957   const DataArrayDouble *coords=meshes.front()->getCoords();
7958   int meshDim=meshes.front()->getMeshDimension();
7959   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7960   int meshLgth=0;
7961   int meshIndexLgth=0;
7962   for(;iter!=meshes.end();iter++)
7963     {
7964       if(coords!=(*iter)->getCoords())
7965         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7966       if(meshDim!=(*iter)->getMeshDimension())
7967         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7968       meshLgth+=(*iter)->getMeshLength();
7969       meshIndexLgth+=(*iter)->getNumberOfCells();
7970     }
7971   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7972   nodal->alloc(meshLgth,1);
7973   int *nodalPtr=nodal->getPointer();
7974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7975   nodalIndex->alloc(meshIndexLgth+1,1);
7976   int *nodalIndexPtr=nodalIndex->getPointer();
7977   int offset=0;
7978   for(iter=meshes.begin();iter!=meshes.end();iter++)
7979     {
7980       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7981       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7982       int nbOfCells=(*iter)->getNumberOfCells();
7983       int meshLgth2=(*iter)->getMeshLength();
7984       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7985       if(iter!=meshes.begin())
7986         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7987       else
7988         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7989       offset+=meshLgth2;
7990     }
7991   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7992   ret->setName("merge");
7993   ret->setMeshDimension(meshDim);
7994   ret->setConnectivity(nodal,nodalIndex,true);
7995   ret->setCoords(coords);
7996   return ret;
7997 }
7998
7999 /*!
8000  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8001  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8002  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8003  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8004  * New" mode are returned for each input mesh.
8005  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8006  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8007  *          valid values [0,1,2], see zipConnectivityTraducer().
8008  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8009  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8010  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8011  *          no more needed.
8012  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8013  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8014  *          is no more needed.
8015  *  \throw If \a meshes.size() == 0.
8016  *  \throw If \a meshes[ *i* ] == NULL.
8017  *  \throw If the meshes do not share the node coordinates array.
8018  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8019  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8020  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8021  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8022  */
8023 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8024 {
8025   //All checks are delegated to MergeUMeshesOnSameCoords
8026   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8027   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8028   corr.resize(meshes.size());
8029   std::size_t nbOfMeshes=meshes.size();
8030   int offset=0;
8031   const int *o2nPtr=o2n->getConstPointer();
8032   for(std::size_t i=0;i<nbOfMeshes;i++)
8033     {
8034       DataArrayInt *tmp=DataArrayInt::New();
8035       int curNbOfCells=meshes[i]->getNumberOfCells();
8036       tmp->alloc(curNbOfCells,1);
8037       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8038       offset+=curNbOfCells;
8039       tmp->setName(meshes[i]->getName());
8040       corr[i]=tmp;
8041     }
8042   return ret.retn();
8043 }
8044
8045 /*!
8046  * Makes all given meshes share the nodal connectivity array. The common connectivity
8047  * array is created by concatenating the connectivity arrays of all given meshes. All
8048  * the given meshes must be of the same space dimension but dimension of cells **can
8049  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8050  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8051  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8052  *  \param [in,out] meshes - a vector of meshes to update.
8053  *  \throw If any of \a meshes is NULL.
8054  *  \throw If the coordinates array is not set in any of \a meshes.
8055  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8056  *  \throw If \a meshes are of different space dimension.
8057  */
8058 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8059 {
8060   std::size_t sz=meshes.size();
8061   if(sz==0 || sz==1)
8062     return;
8063   std::vector< const DataArrayDouble * > coords(meshes.size());
8064   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8065   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8066     {
8067       if((*it))
8068         {
8069           (*it)->checkConnectivityFullyDefined();
8070           const DataArrayDouble *coo=(*it)->getCoords();
8071           if(coo)
8072             *it2=coo;
8073           else
8074             {
8075               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8076               oss << " has no coordinate array defined !";
8077               throw INTERP_KERNEL::Exception(oss.str().c_str());
8078             }
8079         }
8080       else
8081         {
8082           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8083           oss << " is null !";
8084           throw INTERP_KERNEL::Exception(oss.str().c_str());
8085         }
8086     }
8087   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8088   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8089   int offset=(*it)->getNumberOfNodes();
8090   (*it++)->setCoords(res);
8091   for(;it!=meshes.end();it++)
8092     {
8093       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8094       (*it)->setCoords(res);
8095       (*it)->shiftNodeNumbersInConn(offset);
8096       offset+=oldNumberOfNodes;
8097     }
8098 }
8099
8100 /*!
8101  * Merges nodes coincident with a given precision within all given meshes that share
8102  * the nodal connectivity array. The given meshes **can be of different** mesh
8103  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8104  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8105  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8106  *  \param [in,out] meshes - a vector of meshes to update.
8107  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8108  *  \throw If any of \a meshes is NULL.
8109  *  \throw If the \a meshes do not share the same node coordinates array.
8110  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8111  */
8112 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8113 {
8114   if(meshes.empty())
8115     return ;
8116   std::set<const DataArrayDouble *> s;
8117   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8118     {
8119       if(*it)
8120         s.insert((*it)->getCoords());
8121       else
8122         {
8123           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 !";
8124           throw INTERP_KERNEL::Exception(oss.str().c_str());
8125         }
8126     }
8127   if(s.size()!=1)
8128     {
8129       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 !";
8130       throw INTERP_KERNEL::Exception(oss.str().c_str());
8131     }
8132   const DataArrayDouble *coo=*(s.begin());
8133   if(!coo)
8134     return;
8135   //
8136   DataArrayInt *comm,*commI;
8137   coo->findCommonTuples(eps,-1,comm,commI);
8138   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8139   int oldNbOfNodes=coo->getNumberOfTuples();
8140   int newNbOfNodes;
8141   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8142   if(oldNbOfNodes==newNbOfNodes)
8143     return ;
8144   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8145   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8146     {
8147       (*it)->renumberNodesInConn(o2n->getConstPointer());
8148       (*it)->setCoords(newCoords);
8149     } 
8150 }
8151
8152 /*!
8153  * 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.
8154  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8155  * \param isQuad specifies the policy of connectivity.
8156  * @ret in/out parameter in which the result will be append
8157  */
8158 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8159 {
8160   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8161   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8162   ret.push_back(cm.getExtrudedType());
8163   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8164   switch(flatType)
8165   {
8166     case INTERP_KERNEL::NORM_POINT1:
8167       {
8168         ret.push_back(connBg[1]);
8169         ret.push_back(connBg[1]+nbOfNodesPerLev);
8170         break;
8171       }
8172     case INTERP_KERNEL::NORM_SEG2:
8173       {
8174         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8175         ret.insert(ret.end(),conn,conn+4);
8176         break;
8177       }
8178     case INTERP_KERNEL::NORM_SEG3:
8179       {
8180         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8181         ret.insert(ret.end(),conn,conn+8);
8182         break;
8183       }
8184     case INTERP_KERNEL::NORM_QUAD4:
8185       {
8186         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8187         ret.insert(ret.end(),conn,conn+8);
8188         break;
8189       }
8190     case INTERP_KERNEL::NORM_TRI3:
8191       {
8192         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8193         ret.insert(ret.end(),conn,conn+6);
8194         break;
8195       }
8196     case INTERP_KERNEL::NORM_TRI6:
8197       {
8198         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,
8199           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8200         ret.insert(ret.end(),conn,conn+15);
8201         break;
8202       }
8203     case INTERP_KERNEL::NORM_QUAD8:
8204       {
8205         int conn[20]={
8206           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8207           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8208           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8209         };
8210         ret.insert(ret.end(),conn,conn+20);
8211         break;
8212       }
8213     case INTERP_KERNEL::NORM_POLYGON:
8214       {
8215         std::back_insert_iterator< std::vector<int> > ii(ret);
8216         std::copy(connBg+1,connEnd,ii);
8217         *ii++=-1;
8218         std::reverse_iterator<const int *> rConnBg(connEnd);
8219         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8220         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8221         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8222         for(std::size_t i=0;i<nbOfRadFaces;i++)
8223           {
8224             *ii++=-1;
8225             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8226             std::copy(conn,conn+4,ii);
8227           }
8228         break;
8229       }
8230     default:
8231       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8232   }
8233 }
8234
8235 /*!
8236  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8237  */
8238 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8239 {
8240   std::size_t i, ip1;
8241   double v[3]={0.,0.,0.};
8242   std::size_t sz=std::distance(begin,end);
8243   if(isQuadratic)
8244     sz/=2;
8245   for(i=0;i<sz;i++)
8246     {
8247       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];
8248       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8249       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8250     }
8251   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8252
8253   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8254   // SEG3 forming a circle):
8255   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8256     {
8257       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8258       for(std::size_t j=0;j<sz;j++)
8259         {
8260           if (j%2)  // current point i is quadratic, next point i+1 is standard
8261             {
8262               i = sz+j;
8263               ip1 = (j+1)%sz; // ip1 = "i+1"
8264             }
8265           else      // current point i is standard, next point i+1 is quadratic
8266             {
8267               i = j;
8268               ip1 = j+sz;
8269             }
8270           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8271           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8272           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8273         }
8274       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8275     }
8276   return (ret>0.);
8277 }
8278
8279 /*!
8280  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8281  */
8282 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8283 {
8284   std::vector<std::pair<int,int> > edges;
8285   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8286   const int *bgFace=begin;
8287   for(std::size_t i=0;i<nbOfFaces;i++)
8288     {
8289       const int *endFace=std::find(bgFace+1,end,-1);
8290       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8291       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8292         {
8293           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8294           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8295             return false;
8296           edges.push_back(p1);
8297         }
8298       bgFace=endFace+1;
8299     }
8300   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8301 }
8302
8303 /*!
8304  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8305  */
8306 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8307 {
8308   double vec0[3],vec1[3];
8309   std::size_t sz=std::distance(begin,end);
8310   if(sz%2!=0)
8311     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8312   int nbOfNodes=(int)sz/2;
8313   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8314   const double *pt0=coords+3*begin[0];
8315   const double *pt1=coords+3*begin[nbOfNodes];
8316   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8317   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8318 }
8319
8320 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8321 {
8322   std::size_t sz=std::distance(begin,end);
8323   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8324   std::size_t nbOfNodes(sz/2);
8325   std::copy(begin,end,(int *)tmp);
8326   for(std::size_t j=1;j<nbOfNodes;j++)
8327     {
8328       begin[j]=tmp[nbOfNodes-j];
8329       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8330     }
8331 }
8332
8333 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8334 {
8335   std::size_t sz=std::distance(begin,end);
8336   if(sz!=4)
8337     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8338   double vec0[3],vec1[3];
8339   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8340   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]; 
8341   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;
8342 }
8343
8344 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8345 {
8346   std::size_t sz=std::distance(begin,end);
8347   if(sz!=5)
8348     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8349   double vec0[3];
8350   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8351   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8352   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8353 }
8354
8355 /*!
8356  * 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 ) 
8357  * 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
8358  * a 2D space.
8359  *
8360  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8361  * \param [in] coords the coordinates with nb of components exactly equal to 3
8362  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8363  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8364  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8365  */
8366 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8367 {
8368   int nbFaces=std::count(begin+1,end,-1)+1;
8369   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8370   double *vPtr=v->getPointer();
8371   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8372   double *pPtr=p->getPointer();
8373   const int *stFaceConn=begin+1;
8374   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8375     {
8376       const int *endFaceConn=std::find(stFaceConn,end,-1);
8377       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8378       stFaceConn=endFaceConn+1;
8379     }
8380   pPtr=p->getPointer(); vPtr=v->getPointer();
8381   DataArrayInt *comm1=0,*commI1=0;
8382   v->findCommonTuples(eps,-1,comm1,commI1);
8383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8384   const int *comm1Ptr=comm1->getConstPointer();
8385   const int *commI1Ptr=commI1->getConstPointer();
8386   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8387   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8388   //
8389   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8390   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8391   mm->finishInsertingCells();
8392   //
8393   for(int i=0;i<nbOfGrps1;i++)
8394     {
8395       int vecId=comm1Ptr[commI1Ptr[i]];
8396       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8397       DataArrayInt *comm2=0,*commI2=0;
8398       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8399       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8400       const int *comm2Ptr=comm2->getConstPointer();
8401       const int *commI2Ptr=commI2->getConstPointer();
8402       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8403       for(int j=0;j<nbOfGrps2;j++)
8404         {
8405           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8406             {
8407               res->insertAtTheEnd(begin,end);
8408               res->pushBackSilent(-1);
8409             }
8410           else
8411             {
8412               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8413               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8414               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8415               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8416               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8417               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8418               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8419               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8420               const int *idsNodePtr=idsNode->getConstPointer();
8421               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];
8422               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8423               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8424               if(std::abs(norm)>eps)
8425                 {
8426                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8427                   mm3->rotate(center,vec,angle);
8428                 }
8429               mm3->changeSpaceDimension(2);
8430               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8431               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8432               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8433               int nbOfCells=mm4->getNumberOfCells();
8434               for(int k=0;k<nbOfCells;k++)
8435                 {
8436                   int l=0;
8437                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8438                     res->pushBackSilent(idsNodePtr[*work]);
8439                   res->pushBackSilent(-1);
8440                 }
8441             }
8442         }
8443     }
8444   res->popBackSilent();
8445 }
8446
8447 /*!
8448  * 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
8449  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8450  * 
8451  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8452  * \param [in] coords coordinates expected to have 3 components.
8453  * \param [in] begin start of the nodal connectivity of the face.
8454  * \param [in] end end of the nodal connectivity (excluded) of the face.
8455  * \param [out] v the normalized vector of size 3
8456  * \param [out] p the pos of plane
8457  */
8458 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8459 {
8460   std::size_t nbPoints=std::distance(begin,end);
8461   if(nbPoints<3)
8462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8463   double vec[3]={0.,0.,0.};
8464   std::size_t j=0;
8465   bool refFound=false;
8466   for(;j<nbPoints-1 && !refFound;j++)
8467     {
8468       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8469       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8470       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8471       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8472       if(norm>eps)
8473         {
8474           refFound=true;
8475           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8476         }
8477     }
8478   for(std::size_t i=j;i<nbPoints-1;i++)
8479     {
8480       double curVec[3];
8481       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8482       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8483       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8484       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8485       if(norm<eps)
8486         continue;
8487       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8488       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];
8489       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8490       if(norm>eps)
8491         {
8492           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8493           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8494           return ;
8495         }
8496     }
8497   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8498 }
8499
8500 /*!
8501  * This method tries to obtain a well oriented polyhedron.
8502  * If the algorithm fails, an exception will be thrown.
8503  */
8504 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8505 {
8506   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8507   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8508   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8509   isPerm[0]=true;
8510   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8511   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8512   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8513   //
8514   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8515     {
8516       bgFace=begin;
8517       std::size_t smthChanged=0;
8518       for(std::size_t i=0;i<nbOfFaces;i++)
8519         {
8520           endFace=std::find(bgFace+1,end,-1);
8521           nbOfEdgesInFace=std::distance(bgFace,endFace);
8522           if(!isPerm[i])
8523             {
8524               bool b;
8525               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8526                 {
8527                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8528                   std::pair<int,int> p2(p1.second,p1.first);
8529                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8530                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8531                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8532                 }
8533               if(isPerm[i])
8534                 { 
8535                   if(!b)
8536                     std::reverse(bgFace+1,endFace);
8537                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8538                     {
8539                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8540                       std::pair<int,int> p2(p1.second,p1.first);
8541                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8542                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8543                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8544                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8545                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8546                       if(it!=edgesOK.end())
8547                         {
8548                           edgesOK.erase(it);
8549                           edgesFinished.push_back(p1);
8550                         }
8551                       else
8552                         edgesOK.push_back(p1);
8553                     }
8554                 }
8555             }
8556           bgFace=endFace+1;
8557         }
8558       if(smthChanged==0)
8559         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8560     }
8561   if(!edgesOK.empty())
8562     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8563   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8564     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8565       bgFace=begin;
8566       for(std::size_t i=0;i<nbOfFaces;i++)
8567         {
8568           endFace=std::find(bgFace+1,end,-1);
8569           std::reverse(bgFace+1,endFace);
8570           bgFace=endFace+1;
8571         }
8572     }
8573 }
8574
8575 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8576 {
8577   int nbOfNodesExpected(skin->getNumberOfNodes());
8578   const int *n2oPtr(n2o->getConstPointer());
8579   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8580   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8581   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8582   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8583   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8584   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8585   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8586   if(nbOfNodesExpected<1)
8587     return ret.retn();
8588   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8589   *work++=n2oPtr[prevNode];
8590   for(int i=1;i<nbOfNodesExpected;i++)
8591     {
8592       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8593         {
8594           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8595           conn.erase(prevNode);
8596           if(conn.size()==1)
8597             {
8598               int curNode(*(conn.begin()));
8599               *work++=n2oPtr[curNode];
8600               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8601               shar.erase(prevCell);
8602               if(shar.size()==1)
8603                 {
8604                   prevCell=*(shar.begin());
8605                   prevNode=curNode;
8606                 }
8607               else
8608                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8609             }
8610           else
8611             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8612         }
8613       else
8614         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8615     }
8616   return ret.retn();
8617 }
8618
8619 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8620 {
8621   int nbOfNodesExpected(skin->getNumberOfNodes());
8622   int nbOfTurn(nbOfNodesExpected/2);
8623   const int *n2oPtr(n2o->getConstPointer());
8624   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8625   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8626   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8627   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8628   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8630   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8631   if(nbOfNodesExpected<1)
8632     return ret.retn();
8633   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8634   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8635   for(int i=1;i<nbOfTurn;i++)
8636     {
8637       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8638         {
8639           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8640           conn.erase(prevNode);
8641           if(conn.size()==1)
8642             {
8643               int curNode(*(conn.begin()));
8644               *work=n2oPtr[curNode];
8645               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8646               shar.erase(prevCell);
8647               if(shar.size()==1)
8648                 {
8649                   int curCell(*(shar.begin()));
8650                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8651                   prevCell=curCell;
8652                   prevNode=curNode;
8653                   work++;
8654                 }
8655               else
8656                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8657             }
8658           else
8659             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8660         }
8661       else
8662         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8663     }
8664   return ret.retn();
8665 }
8666
8667 /*!
8668  * This method makes the assumption spacedimension == meshdimension == 2.
8669  * This method works only for linear cells.
8670  * 
8671  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8672  */
8673 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8674 {
8675   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8676     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8677   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8678   int oldNbOfNodes(skin->getNumberOfNodes());
8679   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8680   int nbOfNodesExpected(skin->getNumberOfNodes());
8681   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8682   int nbCells(skin->getNumberOfCells());
8683   if(nbCells==nbOfNodesExpected)
8684     return buildUnionOf2DMeshLinear(skin,n2o);
8685   else if(2*nbCells==nbOfNodesExpected)
8686     return buildUnionOf2DMeshQuadratic(skin,n2o);
8687   else
8688     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8689 }
8690
8691 /*!
8692  * This method makes the assumption spacedimension == meshdimension == 3.
8693  * This method works only for linear cells.
8694  * 
8695  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8696  */
8697 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8698 {
8699   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8700     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8701   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8702   const int *conn=m->getNodalConnectivity()->getConstPointer();
8703   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8704   int nbOfCells=m->getNumberOfCells();
8705   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8706   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8707   if(nbOfCells<1)
8708     return ret.retn();
8709   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8710   for(int i=1;i<nbOfCells;i++)
8711     {
8712       *work++=-1;
8713       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8714     }
8715   return ret.retn();
8716 }
8717
8718 /*!
8719  * \brief Creates a graph of cell neighbors
8720  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8721  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8722  *  For example
8723  *  - index:  0 3 5 6 6
8724  *  - value:  1 2 3 2 3 3
8725  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8726  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8727  */
8728 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8729 {
8730   checkConnectivityFullyDefined();
8731
8732   int meshDim = this->getMeshDimension();
8733   ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8734   ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8735   this->getReverseNodalConnectivity(revConn,indexr);
8736   const int* indexr_ptr=indexr->getConstPointer();
8737   const int* revConn_ptr=revConn->getConstPointer();
8738
8739   const ParaMEDMEM::DataArrayInt* index;
8740   const ParaMEDMEM::DataArrayInt* conn;
8741   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8742   index=this->getNodalConnectivityIndex();
8743   int nbCells=this->getNumberOfCells();
8744   const int* index_ptr=index->getConstPointer();
8745   const int* conn_ptr=conn->getConstPointer();
8746
8747   //creating graph arcs (cell to cell relations)
8748   //arcs are stored in terms of (index,value) notation
8749   // 0 3 5 6 6
8750   // 1 2 3 2 3 3
8751   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8752   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8753
8754   //warning here one node have less than or equal effective number of cell with it
8755   //but cell could have more than effective nodes
8756   //because other equals nodes in other domain (with other global inode)
8757   std::vector <int> cell2cell_index(nbCells+1,0);
8758   std::vector <int> cell2cell;
8759   cell2cell.reserve(3*nbCells);
8760
8761   for (int icell=0; icell<nbCells;icell++)
8762     {
8763       std::map<int,int > counter;
8764       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8765         {
8766           int inode=conn_ptr[iconn];
8767           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8768             {
8769               int icell2=revConn_ptr[iconnr];
8770               std::map<int,int>::iterator iter=counter.find(icell2);
8771               if (iter!=counter.end()) (iter->second)++;
8772               else counter.insert(std::make_pair(icell2,1));
8773             }
8774         }
8775       for (std::map<int,int>::const_iterator iter=counter.begin();
8776            iter!=counter.end(); iter++)
8777         if (iter->second >= meshDim)
8778           {
8779             cell2cell_index[icell+1]++;
8780             cell2cell.push_back(iter->first);
8781           }
8782     }
8783   indexr->decrRef();
8784   revConn->decrRef();
8785   cell2cell_index[0]=0;
8786   for (int icell=0; icell<nbCells;icell++)
8787     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8788
8789   //filling up index and value to create skylinearray structure
8790   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8791   return array;
8792 }
8793
8794 /*!
8795  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8796  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8797  */
8798 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8799 {
8800   double *w=zipFrmt;
8801   if(spaceDim==3)
8802     for(int i=0;i<nbOfNodesInCell;i++)
8803       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8804   else if(spaceDim==2)
8805     {
8806       for(int i=0;i<nbOfNodesInCell;i++)
8807         {
8808           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8809           *w++=0.;
8810         }
8811     }
8812   else
8813     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8814 }
8815
8816 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8817 {
8818   int nbOfCells=getNumberOfCells();
8819   if(nbOfCells<=0)
8820     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8821   static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,36,4};
8822   ofs << "  <" << getVTKDataSetType() << ">\n";
8823   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8824   ofs << "      <PointData>\n" << pointData << std::endl;
8825   ofs << "      </PointData>\n";
8826   ofs << "      <CellData>\n" << cellData << std::endl;
8827   ofs << "      </CellData>\n";
8828   ofs << "      <Points>\n";
8829   if(getSpaceDimension()==3)
8830     _coords->writeVTK(ofs,8,"Points",byteData);
8831   else
8832     {
8833       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8834       coo->writeVTK(ofs,8,"Points",byteData);
8835     }
8836   ofs << "      </Points>\n";
8837   ofs << "      <Cells>\n";
8838   const int *cPtr=_nodal_connec->getConstPointer();
8839   const int *cIPtr=_nodal_connec_index->getConstPointer();
8840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8842   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8843   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8844   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8845   int szFaceOffsets=0,szConn=0;
8846   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8847     {
8848       *w2=cPtr[cIPtr[i]];
8849       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8850         {
8851           *w1=-1;
8852           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8853           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8854         }
8855       else
8856         {
8857           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8858           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8859           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8860           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8861           w4=std::copy(c.begin(),c.end(),w4);
8862         }
8863     }
8864   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8865   types->writeVTK(ofs,8,"UInt8","types",byteData);
8866   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8867   if(szFaceOffsets!=0)
8868     {//presence of Polyhedra
8869       connectivity->reAlloc(szConn);
8870       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8871       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8872       w1=faces->getPointer();
8873       for(int i=0;i<nbOfCells;i++)
8874         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8875           {
8876             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8877             *w1++=nbFaces;
8878             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8879             for(int j=0;j<nbFaces;j++)
8880               {
8881                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8882                 *w1++=(int)std::distance(w6,w5);
8883                 w1=std::copy(w6,w5,w1);
8884                 w6=w5+1;
8885               }
8886           }
8887       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8888     }
8889   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8890   ofs << "      </Cells>\n";
8891   ofs << "    </Piece>\n";
8892   ofs << "  </" << getVTKDataSetType() << ">\n";
8893 }
8894
8895 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8896 {
8897   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8898   if(_mesh_dim==-2)
8899     { stream << " Not set !"; return ; }
8900   stream << " Mesh dimension : " << _mesh_dim << ".";
8901   if(_mesh_dim==-1)
8902     return ;
8903   if(!_coords)
8904     { stream << " No coordinates set !"; return ; }
8905   if(!_coords->isAllocated())
8906     { stream << " Coordinates set but not allocated !"; return ; }
8907   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8908   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8909   if(!_nodal_connec_index)
8910     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8911   if(!_nodal_connec_index->isAllocated())
8912     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8913   int lgth=_nodal_connec_index->getNumberOfTuples();
8914   int cpt=_nodal_connec_index->getNumberOfComponents();
8915   if(cpt!=1 || lgth<1)
8916     return ;
8917   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8918 }
8919
8920 std::string MEDCouplingUMesh::getVTKDataSetType() const
8921 {
8922   return std::string("UnstructuredGrid");
8923 }
8924
8925 std::string MEDCouplingUMesh::getVTKFileExtension() const
8926 {
8927   return std::string("vtu");
8928 }
8929
8930 /*!
8931  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8932  * returns a result mesh constituted by polygons.
8933  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8934  * all nodes from m2.
8935  * The meshes should be in 2D space. In
8936  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8937  * meshes.
8938  *  \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
8939  *                      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)
8940  *  \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
8941  *                      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)
8942  *  \param [in] eps - precision used to detect coincident mesh entities.
8943  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8944  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8945  *         this array using decrRef() as it is no more needed.
8946  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8947  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8948  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8949  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8950  *         it is no more needed.  
8951  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8952  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8953  *         is no more needed.  
8954  *  \throw If the coordinates array is not set in any of the meshes.
8955  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8956  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8957  *
8958  *  \sa conformize2D, mergeNodes
8959  */
8960 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8961                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8962 {
8963   if(!m1 || !m2)
8964     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8965   m1->checkFullyDefined();
8966   m2->checkFullyDefined();
8967   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8968     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8969
8970   // Step 1: compute all edge intersections (new nodes)
8971   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8972   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8973   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8974   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8975   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8976                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8977                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8978   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8979   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8980   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8981
8982   // Step 2: re-order newly created nodes according to the ordering found in m2
8983   std::vector< std::vector<int> > intersectEdge2;
8984   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8985   subDiv2.clear(); dd5=0; dd6=0;
8986
8987   // Step 3:
8988   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8989   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8990   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8991                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8992
8993   // Step 4: Prepare final result:
8994   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8995   addCooDa->alloc((int)(addCoo.size())/2,2);
8996   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8997   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8998   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8999   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9000   std::vector<const DataArrayDouble *> coordss(4);
9001   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9002   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9003   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9004   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9005   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9006   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9007   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9008   ret->setConnectivity(conn,connI,true);
9009   ret->setCoords(coo);
9010   cellNb1=c1.retn(); cellNb2=c2.retn();
9011   return ret.retn();
9012 }
9013
9014 /// @cond INTERNAL
9015
9016 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9017 {
9018   if(candidates.empty())
9019     return false;
9020   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9021     {
9022       const std::vector<int>& pool(intersectEdge1[*it]);
9023       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9024       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9025         {
9026           retVal=*it+1;
9027           return true;
9028         }
9029       tmp[0]=stop; tmp[1]=start;
9030       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9031         {
9032           retVal=-*it-1;
9033           return true;
9034         }
9035     }
9036   return false;
9037 }
9038
9039 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,
9040                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9041 {
9042   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9043   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9044   int nCells(mesh1D->getNumberOfCells());
9045   if(nCells!=(int)intersectEdge2.size())
9046     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9047   const DataArrayDouble *coo2(mesh1D->getCoords());
9048   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9049   const double *coo2Ptr(coo2->begin());
9050   int offset1(coords1->getNumberOfTuples());
9051   int offset2(offset1+coo2->getNumberOfTuples());
9052   int offset3(offset2+addCoo.size()/2);
9053   std::vector<double> addCooQuad;
9054   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9055   int tmp[4],cicnt(0),kk(0);
9056   for(int i=0;i<nCells;i++)
9057     {
9058       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9059       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9060       const std::vector<int>& subEdges(intersectEdge2[i]);
9061       int nbSubEdge(subEdges.size()/2);
9062       for(int j=0;j<nbSubEdge;j++,kk++)
9063         {
9064           MEDCouplingAutoRefCountObjectPtr<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));
9065           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9066           INTERP_KERNEL::Edge *e2Ptr(e2);
9067           std::map<int,int>::const_iterator itm;
9068           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9069             {
9070               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9071               itm=mergedNodes.find(subEdges[2*j]);
9072               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9073               itm=mergedNodes.find(subEdges[2*j+1]);
9074               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9075               tmp[3]=offset3+(int)addCooQuad.size()/2;
9076               double tmp2[2];
9077               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9078               cicnt+=4;
9079               cOut->insertAtTheEnd(tmp,tmp+4);
9080               ciOut->pushBackSilent(cicnt);
9081             }
9082           else
9083             {
9084               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9085               itm=mergedNodes.find(subEdges[2*j]);
9086               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9087               itm=mergedNodes.find(subEdges[2*j+1]);
9088               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9089               cicnt+=3;
9090               cOut->insertAtTheEnd(tmp,tmp+3);
9091               ciOut->pushBackSilent(cicnt);
9092             }
9093           int tmp00;
9094           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9095             {
9096               idsInRetColinear->pushBackSilent(kk);
9097               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9098             }
9099         }
9100       e->decrRef();
9101     }
9102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9103   ret->setConnectivity(cOut,ciOut,true);
9104   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9105   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9106   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9107   std::vector<const DataArrayDouble *> coordss(4);
9108   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9109   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9110   ret->setCoords(arr);
9111   return ret.retn();
9112 }
9113
9114 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9115 {
9116   std::vector<int> allEdges;
9117   for(const int *it2(descBg);it2!=descEnd;it2++)
9118     {
9119       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9120       if(*it2>0)
9121         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9122       else
9123         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9124     }
9125   std::size_t nb(allEdges.size());
9126   if(nb%2!=0)
9127     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9128   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9129   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9130   ret->setCoords(coords);
9131   ret->allocateCells(1);
9132   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9133   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9134     connOut[kk]=allEdges[2*kk];
9135   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9136   return ret.retn();
9137 }
9138
9139 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9140 {
9141   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9142   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9143   std::size_t ii(0);
9144   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9145   if(sz!=std::distance(descBg,descEnd))
9146     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9147   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9148   std::vector<int> allEdges,centers;
9149   const double *coordsPtr(coords->begin());
9150   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9151   int offset(coords->getNumberOfTuples());
9152   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9153     {
9154       INTERP_KERNEL::NormalizedCellType typeOfSon;
9155       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9156       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9157       if(*it2>0)
9158         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9159       else
9160         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9161       if(edge1.size()==2)
9162         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9163       else
9164         {//the current edge has been subsplit -> create corresponding centers.
9165           std::size_t nbOfCentersToAppend(edge1.size()/2);
9166           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9167           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9168           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9169           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9170             {
9171               double tmpp[2];
9172               const double *aa(coordsPtr+2*(*it3++));
9173               const double *bb(coordsPtr+2*(*it3++));
9174               ee->getMiddleOfPoints(aa,bb,tmpp);
9175               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9176               centers.push_back(offset+k);
9177             }
9178         }
9179     }
9180   std::size_t nb(allEdges.size());
9181   if(nb%2!=0)
9182     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9183   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9184   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9185   if(addCoo->empty())
9186     ret->setCoords(coords);
9187   else
9188     {
9189       addCoo->rearrange(2);
9190       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9191       ret->setCoords(addCoo);
9192     }
9193   ret->allocateCells(1);
9194   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9195   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9196     connOut[kk]=allEdges[2*kk];
9197   connOut.insert(connOut.end(),centers.begin(),centers.end());
9198   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9199   return ret.retn();
9200 }
9201
9202 /*!
9203  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9204  * of those edges.
9205  *
9206  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9207  */
9208 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9209 {
9210   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9211   if(!cm.isQuadratic())
9212     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9213   else
9214     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9215 }
9216
9217 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9218 {
9219   bool isQuad(false);
9220   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9221     {
9222       const INTERP_KERNEL::Edge *ee(*it);
9223       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9224         isQuad=true;
9225     }
9226   if(!isQuad)
9227     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9228   else
9229     {
9230       const double *coo(mesh2D->getCoords()->begin());
9231       std::size_t sz(conn.size());
9232       std::vector<double> addCoo;
9233       std::vector<int> conn2(conn);
9234       int offset(mesh2D->getNumberOfNodes());
9235       for(std::size_t i=0;i<sz;i++)
9236         {
9237           double tmp[2];
9238           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9239           addCoo.insert(addCoo.end(),tmp,tmp+2);
9240           conn2.push_back(offset+(int)i);
9241         }
9242       mesh2D->getCoords()->rearrange(1);
9243       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9244       mesh2D->getCoords()->rearrange(2);
9245       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9246     }
9247 }
9248
9249 /*!
9250  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9251  *
9252  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9253  * a set of edges defined in \a splitMesh1D.
9254  */
9255 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9256                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9257 {
9258   std::size_t nb(edge1Bis.size()/2);
9259   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9260   int iEnd(splitMesh1D->getNumberOfCells());
9261   if(iEnd==0)
9262     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9263   std::size_t ii,jj;
9264   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9265   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9266   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9267   //
9268   if(jj==nb)
9269     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9270       out0.resize(1); out1.resize(1);
9271       std::vector<int>& connOut(out0[0]);
9272       connOut.resize(nbOfEdgesOf2DCellSplit);
9273       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9274       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9275       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9276         {
9277           connOut[kk]=edge1Bis[2*kk];
9278           edgesPtr[kk]=edge1BisPtr[2*kk];
9279         }
9280     }
9281   else
9282     {
9283       // [i,iEnd[ contains the
9284       out0.resize(2); out1.resize(2);
9285       std::vector<int>& connOutLeft(out0[0]);
9286       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9287       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9288       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9289       for(std::size_t k=ii;k<jj+1;k++)
9290         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9291       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9292       for(int ik=0;ik<iEnd;ik++)
9293         {
9294           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9295           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9296           ees[ik]=ee;
9297         }
9298       for(int ik=iEnd-1;ik>=0;ik--)
9299         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9300       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9301         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9302       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9303       for(int ik=0;ik<iEnd;ik++)
9304         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9305       eright.insert(eright.end(),ees.begin(),ees.end());
9306     }
9307 }
9308
9309 /// @endcond
9310
9311 /// @cond INTERNAL
9312
9313 struct CellInfo
9314 {
9315 public:
9316   CellInfo() { }
9317   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9318 public:
9319   std::vector<int> _edges;
9320   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9321 };
9322
9323 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9324 {
9325   std::size_t nbe(edges.size());
9326   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9327   for(std::size_t i=0;i<nbe;i++)
9328     {
9329       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9330       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9331     }
9332   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9333   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9334   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9335 }
9336
9337 class EdgeInfo
9338 {
9339 public:
9340   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9341   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9342   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9343   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9344   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9345 private:
9346   int _istart;
9347   int _iend;
9348   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9349   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9350   int _left;
9351   int _right;
9352 };
9353
9354 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9355 {
9356   const MEDCouplingUMesh *mesh(_mesh);
9357   if(mesh)
9358     return ;
9359   if(_right<pos)
9360     return ;
9361   if(_left>pos)
9362     { _left++; _right++; return ; }
9363   if(_right==pos)
9364     {
9365       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9366       if((isLeft && isRight) || (!isLeft && !isRight))
9367         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9368       if(isLeft)
9369         return ;
9370       if(isRight)
9371         {
9372           _right++;
9373           return ;
9374         }
9375     }
9376   if(_left==pos)
9377     {
9378       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9379       if((isLeft && isRight) || (!isLeft && !isRight))
9380         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9381       if(isLeft)
9382         {
9383           _right++;
9384           return ;
9385         }
9386       if(isRight)
9387         {
9388           _left++;
9389           _right++;
9390           return ;
9391         }
9392     }
9393 }
9394
9395 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9396 {
9397   const MEDCouplingUMesh *mesh(_mesh);
9398   if(!mesh)
9399     {
9400       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9401     }
9402   else
9403     {// not fully splitting cell case
9404       if(mesh2D->getNumberOfCells()==1)
9405         {//little optimization. 1 cell no need to find in which cell mesh is !
9406           neighbors[0]=offset; neighbors[1]=offset;
9407           return;
9408         }
9409       else
9410         {
9411           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9412           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9413           if(cellId==-1)
9414             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9415           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9416         }
9417     }
9418 }
9419
9420 class VectorOfCellInfo
9421 {
9422 public:
9423   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9424   std::size_t size() const { return _pool.size(); }
9425   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9426   void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs);
9427   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9428   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9429   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9430   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9431 private:
9432   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9433   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9434   const CellInfo& get(int pos) const;
9435   CellInfo& get(int pos);
9436 private:
9437   std::vector<CellInfo> _pool;
9438   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9439   std::vector<EdgeInfo> _edge_info;
9440 };
9441
9442 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9443 {
9444   _pool[0]._edges=edges;
9445   _pool[0]._edges_ptr=edgesPtr;
9446 }
9447
9448 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9449 {
9450   if(_pool.empty())
9451     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9452   if(_pool.size()==1)
9453     return 0;
9454   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9455   if(!zeMesh)
9456     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9457   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9458   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9459 }
9460
9461 void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs)
9462 {
9463   get(pos);//to check pos
9464   bool isFast(pos==0 && _pool.size()==1);
9465   std::size_t sz(edges.size());
9466   // dealing with edges
9467   if(sz==1)
9468     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9469   else
9470     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9471   //
9472   std::vector<CellInfo> pool(_pool.size()-1+sz);
9473   for(int i=0;i<pos;i++)
9474     pool[i]=_pool[i];
9475   for(std::size_t j=0;j<sz;j++)
9476     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9477   for(int i=pos+1;i<(int)_pool.size();i++)
9478     pool[i+sz-1]=_pool[i];
9479   _pool=pool;
9480   //
9481   if(sz==2)
9482     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9483   //
9484   if(isFast)
9485     {
9486       _ze_mesh=mesh;
9487       return ;
9488     }
9489   //
9490   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9491   if(pos>0)
9492     {
9493       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9494       ms.push_back(elt);
9495     }
9496   ms.push_back(mesh);
9497   if(pos<_ze_mesh->getNumberOfCells()-1)
9498   {
9499     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9500     ms.push_back(elt);
9501   }
9502   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9503   for(std::size_t j=0;j<ms2.size();j++)
9504     ms2[j]=ms[j];
9505   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9506 }
9507
9508 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9509 {
9510   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9511 }
9512
9513 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9514 {
9515   if(pos<0)
9516     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9517   int ret(0);
9518   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9519     {
9520       if((*it).isInMyRange(pos))
9521         return ret;
9522     }
9523   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9524 }
9525
9526 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9527 {
9528   get(pos);//to check;
9529   if(_edge_info.empty())
9530     return ;
9531   std::size_t sz(_edge_info.size()-1);
9532   for(std::size_t i=0;i<sz;i++)
9533     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9534 }
9535
9536 const CellInfo& VectorOfCellInfo::get(int pos) const
9537 {
9538   if(pos<0 || pos>=(int)_pool.size())
9539     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9540   return _pool[pos];
9541 }
9542
9543 CellInfo& VectorOfCellInfo::get(int pos)
9544 {
9545   if(pos<0 || pos>=(int)_pool.size())
9546     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9547   return _pool[pos];
9548 }
9549
9550 /*!
9551  * Given :
9552  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9553  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9554  *
9555  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9556  *
9557  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9558  *
9559  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9560  */
9561 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9562                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9563 {
9564   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9565   if(nbCellsInSplitMesh1D==0)
9566     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9567   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9568   std::size_t nb(allEdges.size()),jj;
9569   if(nb%2!=0)
9570     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9571   std::vector<int> edge1Bis(nb*2);
9572   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9573   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9574   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9575   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9576   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9577   //
9578   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9579   int *idsLeftRightPtr(idsLeftRight->getPointer());
9580   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9581   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9582     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9583       int iEnd(iStart);
9584       for(;iEnd<nbCellsInSplitMesh1D;)
9585         {
9586           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9587           if(jj!=nb)
9588             break;
9589           else
9590             iEnd++;
9591         }
9592       if(iEnd<nbCellsInSplitMesh1D)
9593         iEnd++;
9594       //
9595       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9596       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9597       //
9598       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9599       retTmp->setCoords(splitMesh1D->getCoords());
9600       retTmp->allocateCells();
9601
9602       std::vector< std::vector<int> > out0;
9603       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9604
9605       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9606       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9607         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9608       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9609       //
9610       iStart=iEnd;
9611     }
9612   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9613     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9614   return pool.getZeMesh().retn();
9615 }
9616
9617 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9618                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9619                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9620 {
9621   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9622   //
9623   std::vector<int> allEdges;
9624   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9625   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9626     {
9627       int edgeId(std::abs(*it)-1);
9628       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9629       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9630       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9631       if(*it>0)
9632         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9633       else
9634         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9635       std::size_t sz(edge1.size());
9636       for(std::size_t cnt=0;cnt<sz;cnt++)
9637         allEdgesPtr.push_back(ee);
9638     }
9639   //
9640   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9641 }
9642
9643 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9644 {
9645   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9646     {//easy case comparison not
9647       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9648     }
9649   else if(typ1.isQuadratic() && typ2.isQuadratic())
9650     {
9651       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9652       if(!status0)
9653         return false;
9654       if(conn1[2]==conn2[2])
9655         return true;
9656       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9657       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9658       return dist<eps;
9659     }
9660   else
9661     {//only one is quadratic
9662       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9663       if(!status0)
9664         return false;
9665       const double *a(0),*bb(0),*be(0);
9666       if(typ1.isQuadratic())
9667         {
9668           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9669         }
9670       else
9671         {
9672           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9673         }
9674       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9675       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9676       return dist<eps;
9677     }
9678 }
9679
9680 /*!
9681  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9682  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9683  *
9684  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9685  */
9686 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9687 {
9688   if(candidatesIn2DEnd==candidatesIn2DBg)
9689     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9690   const double *coo(mesh2DSplit->getCoords()->begin());
9691   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9692     return *candidatesIn2DBg;
9693   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9694   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9695   if(cellIdInMesh1DSplitRelative<0)
9696     cur1D->changeOrientationOfCells();
9697   const int *c1D(cur1D->getNodalConnectivity()->begin());
9698   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9699   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9700     {
9701       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9702       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9703       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9704       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9705       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9706       for(unsigned it2=0;it2<sz;it2++)
9707         {
9708           INTERP_KERNEL::NormalizedCellType typeOfSon;
9709           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9710           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9711           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9712             return *it;
9713         }
9714     }
9715   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9716 }
9717
9718 /// @endcond
9719
9720 /*!
9721  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9722  * 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
9723  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9724  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9725  *
9726  * \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
9727  *                      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)
9728  * \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
9729  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9730  * \param [in] eps - precision used to perform intersections and localization operations.
9731  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9732  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9733  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9734  *                               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.
9735  * \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
9736  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9737  *                               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.
9738  *
9739  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9740  */
9741 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9742 {
9743   if(!mesh2D || !mesh1D)
9744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9745   mesh2D->checkFullyDefined();
9746   mesh1D->checkFullyDefined();
9747   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9748   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9749     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9750   // Step 1: compute all edge intersections (new nodes)
9751   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9752   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9753   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9754   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9755   //
9756   // Build desc connectivity
9757   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9759   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9760   std::map<int,int> mergedNodes;
9761   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9762   // use mergeNodes to fix intersectEdge1
9763   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9764     {
9765       std::size_t n((*it0).size()/2);
9766       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9767       std::map<int,int>::const_iterator it1;
9768       it1=mergedNodes.find(eltStart);
9769       if(it1!=mergedNodes.end())
9770         (*it0)[0]=(*it1).second;
9771       it1=mergedNodes.find(eltEnd);
9772       if(it1!=mergedNodes.end())
9773         (*it0)[2*n-1]=(*it1).second;
9774     }
9775   //
9776   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9777   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9778   // Step 2: re-order newly created nodes according to the ordering found in m2
9779   std::vector< std::vector<int> > intersectEdge2;
9780   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9781   subDiv2.clear();
9782   // Step 3: compute splitMesh1D
9783   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9785   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9786       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9788   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9789   // deal with cells in mesh2D that are not cut but only some of their edges are
9790   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9791   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9792   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9793   MEDCouplingAutoRefCountObjectPtr<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
9794   if(!idsInDesc2DToBeRefined->empty())
9795     {
9796       DataArrayInt *out0(0),*outi0(0);
9797       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9798       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9799       out0s=out0;
9800       out0s=out0s->buildUnique();
9801       out0s->sort(true);
9802     }
9803   //
9804   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9805   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9806   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9807   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9810   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9811     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9812   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9814   if((DataArrayInt *)out0s)
9815     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9816   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9817   // OK all is ready to insert in ret2 mesh
9818   if(!untouchedCells->empty())
9819     {// the most easy part, cells in mesh2D not impacted at all
9820       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9821       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9822       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9823     }
9824   if((DataArrayInt *)out0s)
9825     {// here dealing with cells in out0s but not in cellsToBeModified
9826       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9827       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9828       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9829         {
9830           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9831           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9832         }
9833       int offset(ret2->getNumberOfTuples());
9834       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9835       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9836       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9837       int kk(0),*ret3ptr(partOfRet3->getPointer());
9838       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9839         {
9840           int faceId(std::abs(*it)-1);
9841           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9842             {
9843               int tmp(fewModifiedCells->locateValue(*it2));
9844               if(tmp!=-1)
9845                 {
9846                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9847                     ret3ptr[2*kk]=tmp+offset;
9848                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9849                     ret3ptr[2*kk+1]=tmp+offset;
9850                 }
9851               else
9852                 {//the current edge is shared by a 2D cell that will be split just after
9853                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9854                     ret3ptr[2*kk]=-(*it2+1);
9855                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9856                     ret3ptr[2*kk+1]=-(*it2+1);
9857                 }
9858             }
9859         }
9860       m1Desc->setCoords(ret1->getCoords());
9861       ret1NonCol->setCoords(ret1->getCoords());
9862       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9863       if(!outMesh2DSplit.empty())
9864         {
9865           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9866           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9867             (*itt)->setCoords(da);
9868         }
9869     }
9870   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9871   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9872     {
9873       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9874       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9875       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9876       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9877       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9878       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9879       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9880       outMesh2DSplit.push_back(splitOfOneCell);
9881       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9882         ret2->pushBackSilent(*it);
9883     }
9884   //
9885   std::size_t nbOfMeshes(outMesh2DSplit.size());
9886   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9887   for(std::size_t i=0;i<nbOfMeshes;i++)
9888     tmp[i]=outMesh2DSplit[i];
9889   //
9890   ret1->getCoords()->setInfoOnComponents(compNames);
9891   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9892   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9893   ret3->rearrange(1);
9894   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9895   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9896     {
9897       int old2DCellId(-ret3->getIJ(*it,0)-1);
9898       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9899       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
9900     }
9901   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9902   ret3->rearrange(2);
9903   //
9904   splitMesh1D=ret1.retn();
9905   splitMesh2D=ret2D.retn();
9906   cellIdInMesh2D=ret2.retn();
9907   cellIdInMesh1D=ret3.retn();
9908 }
9909
9910 /**
9911  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9912  * (newly created) nodes corresponding to the edge intersections.
9913  * Output params:
9914  * @param[out] cr, crI connectivity of the resulting mesh
9915  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9916  * TODO: describe input parameters
9917  */
9918 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9919                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9920                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9921                                                          const std::vector<double>& addCoords,
9922                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9923 {
9924   static const int SPACEDIM=2;
9925   const double *coo1(m1->getCoords()->getConstPointer());
9926   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9927   int offset1(m1->getNumberOfNodes());
9928   const double *coo2(m2->getCoords()->getConstPointer());
9929   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9930   int offset2(offset1+m2->getNumberOfNodes());
9931   int offset3(offset2+((int)addCoords.size())/2);
9932   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9933   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9934   // Here a BBTree on 2D-cells, not on segments:
9935   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9936   int ncell1(m1->getNumberOfCells());
9937   crI.push_back(0);
9938   for(int i=0;i<ncell1;i++)
9939     {
9940       std::vector<int> candidates2;
9941       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9942       std::map<INTERP_KERNEL::Node *,int> mapp;
9943       std::map<int,INTERP_KERNEL::Node *> mappRev;
9944       INTERP_KERNEL::QuadraticPolygon pol1;
9945       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9946       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9947       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9948       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9949       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9950       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9951           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9952       //
9953       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
9954       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9955       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9956       for(it1.first();!it1.finished();it1.next())
9957         edges1.insert(it1.current()->getPtr());
9958       //
9959       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9960       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9961       int ii=0;
9962       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9963         {
9964           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9965           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9966           // Complete mapping with elements coming from the current cell it2 in mesh2:
9967           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9968           // pol2 is the new QP in the final merged result.
9969           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9970               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9971         }
9972       ii=0;
9973       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9974         {
9975           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9976           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9977           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9978           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9979         }
9980       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9981       // by m2 but that we still want to keep in the final result.
9982       if(!edges1.empty())
9983         {
9984           try
9985           {
9986               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9987           }
9988           catch(INTERP_KERNEL::Exception& e)
9989           {
9990               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();
9991               throw INTERP_KERNEL::Exception(oss.str().c_str());
9992           }
9993         }
9994       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9995         (*it).second->decrRef();
9996     }
9997 }
9998
9999 /**
10000  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10001  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10002  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10003  * The caller is to deal with the resulting DataArrayInt.
10004  *  \throw If the coordinate array is not set.
10005  *  \throw If the nodal connectivity of the cells is not defined.
10006  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10007  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10008  *
10009  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10010  */
10011 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10012 {
10013   checkFullyDefined();
10014   if(getMeshDimension()!=1)
10015     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10016
10017   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10018   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10019   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10020   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10021   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10022   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10023   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10024   const int * dsi(_dsi->getConstPointer());
10025   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10026   m_points=0;
10027   if (dsii->getNumberOfTuples())
10028     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10029
10030   int nc(getNumberOfCells());
10031   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10032   result->alloc(nc,1);
10033
10034   // set of edges not used so far
10035   std::set<int> edgeSet;
10036   for (int i=0; i<nc; edgeSet.insert(i), i++);
10037
10038   int startSeg=0;
10039   int newIdx=0;
10040   // while we have points with only one neighbor segments
10041   do
10042     {
10043       std::list<int> linePiece;
10044       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10045       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10046         {
10047           // Fill the list forward (resp. backward) from the start segment:
10048           int activeSeg = startSeg;
10049           int prevPointId = -20;
10050           int ptId;
10051           while (!edgeSet.empty())
10052             {
10053               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10054                 {
10055                   if (direction==0)
10056                     linePiece.push_back(activeSeg);
10057                   else
10058                     linePiece.push_front(activeSeg);
10059                   edgeSet.erase(activeSeg);
10060                 }
10061
10062               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10063               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10064               if (dsi[ptId] == 1) // hitting the end of the line
10065                 break;
10066               prevPointId = ptId;
10067               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10068               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10069             }
10070         }
10071       // Done, save final piece into DA:
10072       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10073       newIdx += linePiece.size();
10074
10075       // identify next valid start segment (one which is not consumed)
10076       if(!edgeSet.empty())
10077         startSeg = *(edgeSet.begin());
10078     }
10079   while (!edgeSet.empty());
10080   return result.retn();
10081 }
10082
10083 /// @cond INTERNAL
10084
10085 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10086 {
10087   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10088   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10089   if(it==m.end())
10090     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10091   int v((*it).second);
10092   if(v==forbVal0 || v==forbVal1)
10093     return ;
10094   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10095     isect.push_back(v);
10096 }
10097
10098 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10099 {
10100   int sz(c.size());
10101   if(sz<=1)
10102     return false;
10103   bool presenceOfOn(false);
10104   for(int i=0;i<sz;i++)
10105     {
10106       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10107       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10108         continue ;
10109       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10110       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10111     }
10112   return presenceOfOn;
10113 }
10114
10115 /// @endcond
10116
10117 /**
10118  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
10119  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
10120  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
10121  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10122  *
10123  * \return int - the number of new nodes created (in most of cases 0).
10124  * 
10125  * \throw If \a this is not coherent.
10126  * \throw If \a this has not spaceDim equal to 2.
10127  * \throw If \a this has not meshDim equal to 2.
10128  * \throw If some subcells needed to be split are orphan.
10129  * \sa MEDCouplingUMesh::conformize2D
10130  */
10131 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10132 {
10133   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10134     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10135   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10136   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10137     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10138   if(midOpt==0 && midOptI==0)
10139     {
10140       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10141       return 0;
10142     }
10143   else if(midOpt!=0 && midOptI!=0)
10144     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10145   else
10146     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10147 }
10148
10149 /*!
10150  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10151  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10152  * 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
10153  * 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).
10154  * 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.
10155  * 
10156  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10157  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10158  *
10159  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10160  * This method expects that all nodes in \a this are not closer than \a eps.
10161  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10162  * 
10163  * \param [in] eps the relative error to detect merged edges.
10164  * \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
10165  *                           that the user is expected to deal with.
10166  *
10167  * \throw If \a this is not coherent.
10168  * \throw If \a this has not spaceDim equal to 2.
10169  * \throw If \a this has not meshDim equal to 2.
10170  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10171  */
10172 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10173 {
10174   static const int SPACEDIM=2;
10175   checkCoherency();
10176   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10177     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10179   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10180   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10181   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10182   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10183   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10184   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10185   std::vector<double> addCoo;
10186   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10187   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10188   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10189   for(int i=0;i<nDescCell;i++)
10190     {
10191       std::vector<int> candidates;
10192       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10193       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10194         if(*it>i)
10195           {
10196             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10197             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10198                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10199             INTERP_KERNEL::MergePoints merge;
10200             INTERP_KERNEL::QuadraticPolygon c1,c2;
10201             e1->intersectWith(e2,merge,c1,c2);
10202             e1->decrRef(); e2->decrRef();
10203             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10204               overlapEdge[i].push_back(*it);
10205             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10206               overlapEdge[*it].push_back(i);
10207           }
10208     }
10209   // splitting done. sort intersect point in intersectEdge.
10210   std::vector< std::vector<int> > middle(nDescCell);
10211   int nbOf2DCellsToBeSplit(0);
10212   bool middleNeedsToBeUsed(false);
10213   std::vector<bool> cells2DToTreat(nDescCell,false);
10214   for(int i=0;i<nDescCell;i++)
10215     {
10216       std::vector<int>& isect(intersectEdge[i]);
10217       int sz((int)isect.size());
10218       if(sz>1)
10219         {
10220           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10221           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10222           e->sortSubNodesAbs(coords,isect);
10223           e->decrRef();
10224         }
10225       if(sz!=0)
10226         {
10227           int idx0(rdi[i]),idx1(rdi[i+1]);
10228           if(idx1-idx0!=1)
10229             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10230           if(!cells2DToTreat[rd[idx0]])
10231             {
10232               cells2DToTreat[rd[idx0]]=true;
10233               nbOf2DCellsToBeSplit++;
10234             }
10235           // try to reuse at most eventual 'middle' of SEG3
10236           std::vector<int>& mid(middle[i]);
10237           mid.resize(sz+1,-1);
10238           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10239             {
10240               middleNeedsToBeUsed=true;
10241               const std::vector<int>& candidates(overlapEdge[i]);
10242               std::vector<int> trueCandidates;
10243               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10244                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10245                   trueCandidates.push_back(*itc);
10246               int stNode(c[ci[i]+1]),endNode(isect[0]);
10247               for(int j=0;j<sz+1;j++)
10248                 {
10249                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10250                     {
10251                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10252                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10253                         { mid[j]=*itc; break; }
10254                     }
10255                   stNode=endNode;
10256                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10257                 }
10258             }
10259         }
10260     }
10261   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10262   if(nbOf2DCellsToBeSplit==0)
10263     return ret.retn();
10264   //
10265   int *retPtr(ret->getPointer());
10266   for(int i=0;i<nCell;i++)
10267     if(cells2DToTreat[i])
10268       *retPtr++=i;
10269   //
10270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10271   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10272   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10273   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10274   if(middleNeedsToBeUsed)
10275     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10276   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10277   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10278   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.
10279   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10280   {
10281     bool areNodesMerged; int newNbOfNodes;
10282     if(nbOfNodesCreated!=0)
10283       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10284   }
10285   return ret.retn();
10286 }
10287
10288 /*!
10289  * 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.
10290  * 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).
10291  * 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
10292  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10293  * 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
10294  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10295  *
10296  * 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
10297  * using new instance, idem for coordinates.
10298  *
10299  * 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.
10300  * 
10301  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10302  *
10303  * \throw If \a this is not coherent.
10304  * \throw If \a this has not spaceDim equal to 2.
10305  * \throw If \a this has not meshDim equal to 2.
10306  * 
10307  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10308  */
10309 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10310 {
10311   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10312   checkCoherency();
10313   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10314     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10315   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10316   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10317   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10318   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10320   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10321   const double *coords(_coords->begin());
10322   int *newciptr(newci->getPointer());
10323   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10324     {
10325       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10326         ret->pushBackSilent(i);
10327       newciptr[1]=newc->getNumberOfTuples();
10328     }
10329   //
10330   if(ret->empty())
10331     return ret.retn();
10332   if(!appendedCoords->empty())
10333     {
10334       appendedCoords->rearrange(2);
10335       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10336       //non const part
10337       setCoords(newCoords);
10338     }
10339   //non const part
10340   setConnectivity(newc,newci,true);
10341   return ret.retn();
10342 }
10343
10344 /*!
10345  * \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.
10346  *                               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.
10347  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10348  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10349  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10350  * \param [out] addCoo - nodes to be append at the end
10351  * \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.
10352  */
10353 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10354                                          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)
10355 {
10356   static const int SPACEDIM=2;
10357   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10358   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10359   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10360   // Build BB tree of all edges in the tool mesh (second mesh)
10361   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10362   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10363   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10364   intersectEdge1.resize(nDescCell1);
10365   colinear2.resize(nDescCell2);
10366   subDiv2.resize(nDescCell2);
10367   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10368
10369   std::vector<int> candidates1(1);
10370   int offset1(m1Desc->getNumberOfNodes());
10371   int offset2(offset1+m2Desc->getNumberOfNodes());
10372   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10373     {
10374       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10375       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10376       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10377         {
10378           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10379           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10380           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10381           candidates1[0]=i;
10382           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10383           // 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
10384           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10385           std::set<INTERP_KERNEL::Node *> nodes;
10386           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10387           std::size_t szz(nodes.size());
10388           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10389           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10390           for(std::size_t iii=0;iii<szz;iii++,itt++)
10391             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10392           // end of protection
10393           // Performs egde cutting:
10394           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10395           delete pol2;
10396           delete pol1;
10397         }
10398       else
10399         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10400         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10401     }
10402 }
10403
10404 /*!
10405  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10406  * It builds the descending connectivity of the two meshes, and then using a binary tree
10407  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10408  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10409  */
10410 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10411                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10412                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10413                                                    std::vector<double>& addCoo,
10414                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10415 {
10416   // Build desc connectivity
10417   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10418   desc2=DataArrayInt::New();
10419   descIndx2=DataArrayInt::New();
10420   revDesc2=DataArrayInt::New();
10421   revDescIndx2=DataArrayInt::New();
10422   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10423   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10424   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10425   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10426   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10427   std::map<int,int> notUsedMap;
10428   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10429   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10430   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10431 }
10432
10433 /*!
10434  * This method performs the 2nd step of Partition of 2D mesh.
10435  * This method has 4 inputs :
10436  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10437  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10438  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10439  * 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'
10440  * Nodes end up lying consecutively on a cutted edge.
10441  * \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.
10442  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10443  * \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.
10444  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10445  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10446  */
10447 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10448                                            const std::vector<double>& addCoo,
10449                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10450 {
10451   int offset1=m1->getNumberOfNodes();
10452   int ncell=m2->getNumberOfCells();
10453   const int *c=m2->getNodalConnectivity()->getConstPointer();
10454   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10455   const double *coo=m2->getCoords()->getConstPointer();
10456   const double *cooBis=m1->getCoords()->getConstPointer();
10457   int offset2=offset1+m2->getNumberOfNodes();
10458   intersectEdge.resize(ncell);
10459   for(int i=0;i<ncell;i++,cI++)
10460     {
10461       const std::vector<int>& divs=subDiv[i];
10462       int nnode=cI[1]-cI[0]-1;
10463       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10464       std::map<INTERP_KERNEL::Node *, int> mapp22;
10465       for(int j=0;j<nnode;j++)
10466         {
10467           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10468           int nnid=c[(*cI)+j+1];
10469           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10470           mapp22[nn]=nnid+offset1;
10471         }
10472       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10473       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10474         ((*it).second.first)->decrRef();
10475       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10476       std::map<INTERP_KERNEL::Node *,int> mapp3;
10477       for(std::size_t j=0;j<divs.size();j++)
10478         {
10479           int id=divs[j];
10480           INTERP_KERNEL::Node *tmp=0;
10481           if(id<offset1)
10482             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10483           else if(id<offset2)
10484             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10485           else
10486             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10487           addNodes[j]=tmp;
10488           mapp3[tmp]=id;
10489         }
10490       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10491       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10492         (*it)->decrRef();
10493       e->decrRef();
10494     }
10495 }
10496
10497 /*!
10498  * 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).
10499  * 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
10500  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10501  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10502  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10503  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10504  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10505  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10506  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10507  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10508  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10509  * \param [out] cut3DSuf input/output param.
10510  */
10511 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10512                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10513                                                    const int *desc, const int *descIndx, 
10514                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10515 {
10516   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10517   int nbOf3DSurfCell=(int)cut3DSurf.size();
10518   for(int i=0;i<nbOf3DSurfCell;i++)
10519     {
10520       std::vector<int> res;
10521       int offset=descIndx[i];
10522       int nbOfSeg=descIndx[i+1]-offset;
10523       for(int j=0;j<nbOfSeg;j++)
10524         {
10525           int edgeId=desc[offset+j];
10526           int status=cut3DCurve[edgeId];
10527           if(status!=-2)
10528             {
10529               if(status>-1)
10530                 res.push_back(status);
10531               else
10532                 {
10533                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10534                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10535                 }
10536             }
10537         }
10538       switch(res.size())
10539       {
10540         case 2:
10541           {
10542             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10543             break;
10544           }
10545         case 1:
10546         case 0:
10547           {
10548             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10549             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10550             if(res.size()==2)
10551               {
10552                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10553               }
10554             else
10555               {
10556                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10557               }
10558             break;
10559           }
10560         default:
10561           {// case when plane is on a multi colinear edge of a polyhedron
10562             if((int)res.size()==2*nbOfSeg)
10563               {
10564                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10565               }
10566             else
10567               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10568           }
10569       }
10570     }
10571 }
10572
10573 /*!
10574  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10575  * 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).
10576  * 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
10577  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10578  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10579  * \param desc is the descending connectivity 3D->3DSurf
10580  * \param descIndx is the descending connectivity index 3D->3DSurf
10581  */
10582 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10583                                                   const int *desc, const int *descIndx,
10584                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10585 {
10586   checkFullyDefined();
10587   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10588     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10589   const int *nodal3D=_nodal_connec->getConstPointer();
10590   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10591   int nbOfCells=getNumberOfCells();
10592   for(int i=0;i<nbOfCells;i++)
10593     {
10594       std::map<int, std::set<int> > m;
10595       int offset=descIndx[i];
10596       int nbOfFaces=descIndx[i+1]-offset;
10597       int start=-1;
10598       int end=-1;
10599       for(int j=0;j<nbOfFaces;j++)
10600         {
10601           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10602           if(p.first!=-1 && p.second!=-1)
10603             {
10604               if(p.first!=-2)
10605                 {
10606                   start=p.first; end=p.second;
10607                   m[p.first].insert(p.second);
10608                   m[p.second].insert(p.first);
10609                 }
10610               else
10611                 {
10612                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10613                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10614                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10615                   INTERP_KERNEL::NormalizedCellType cmsId;
10616                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10617                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10618                   for(unsigned k=0;k<nbOfNodesSon;k++)
10619                     {
10620                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10621                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10622                     }
10623                 }
10624             }
10625         }
10626       if(m.empty())
10627         continue;
10628       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10629       int prev=end;
10630       while(end!=start)
10631         {
10632           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10633           const std::set<int>& s=(*it).second;
10634           std::set<int> s2; s2.insert(prev);
10635           std::set<int> s3;
10636           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10637           if(s3.size()==1)
10638             {
10639               int val=*s3.begin();
10640               conn.push_back(start);
10641               prev=start;
10642               start=val;
10643             }
10644           else
10645             start=end;
10646         }
10647       conn.push_back(end);
10648       if(conn.size()>3)
10649         {
10650           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10651           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10652           cellIds->pushBackSilent(i);
10653         }
10654     }
10655 }
10656
10657 /*!
10658  * 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
10659  * 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
10660  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10661  * 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
10662  * 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.
10663  * 
10664  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10665  */
10666 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10667 {
10668   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10669   if(sz>=4)
10670     {
10671       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10672       if(cm.getDimension()==2)
10673         {
10674           const int *node=nodalConnBg+1;
10675           int startNode=*node++;
10676           double refX=coords[2*startNode];
10677           for(;node!=nodalConnEnd;node++)
10678             {
10679               if(coords[2*(*node)]<refX)
10680                 {
10681                   startNode=*node;
10682                   refX=coords[2*startNode];
10683                 }
10684             }
10685           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10686           refX=1e300;
10687           double tmp1;
10688           double tmp2[2];
10689           double angle0=-M_PI/2;
10690           //
10691           int nextNode=-1;
10692           int prevNode=-1;
10693           double resRef;
10694           double angleNext=0.;
10695           while(nextNode!=startNode)
10696             {
10697               nextNode=-1;
10698               resRef=1e300;
10699               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10700                 {
10701                   if(*node!=tmpOut.back() && *node!=prevNode)
10702                     {
10703                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10704                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10705                       double res;
10706                       if(angleM<=angle0)
10707                         res=angle0-angleM;
10708                       else
10709                         res=angle0-angleM+2.*M_PI;
10710                       if(res<resRef)
10711                         {
10712                           nextNode=*node;
10713                           resRef=res;
10714                           angleNext=angleM;
10715                         }
10716                     }
10717                 }
10718               if(nextNode!=startNode)
10719                 {
10720                   angle0=angleNext-M_PI;
10721                   if(angle0<-M_PI)
10722                     angle0+=2*M_PI;
10723                   prevNode=tmpOut.back();
10724                   tmpOut.push_back(nextNode);
10725                 }
10726             }
10727           std::vector<int> tmp3(2*(sz-1));
10728           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10729           std::copy(nodalConnBg+1,nodalConnEnd,it);
10730           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10731             {
10732               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10733               return false;
10734             }
10735           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10736             {
10737               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10738               return false;
10739             }
10740           else
10741             {
10742               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10743               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10744               return true;
10745             }
10746         }
10747       else
10748         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10749     }
10750   else
10751     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10752 }
10753
10754 /*!
10755  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10756  * 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.
10757  * 
10758  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10759  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10760  * \param [in,out] arr array in which the remove operation will be done.
10761  * \param [in,out] arrIndx array in the remove operation will modify
10762  * \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])
10763  * \return true if \b arr and \b arrIndx have been modified, false if not.
10764  */
10765 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10766 {
10767   if(!arrIndx || !arr)
10768     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10769   if(offsetForRemoval<0)
10770     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10771   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10772   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10773   int *arrIPtr=arrIndx->getPointer();
10774   *arrIPtr++=0;
10775   int previousArrI=0;
10776   const int *arrPtr=arr->getConstPointer();
10777   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10778   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10779     {
10780       if(*arrIPtr-previousArrI>offsetForRemoval)
10781         {
10782           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10783             {
10784               if(s.find(*work)==s.end())
10785                 arrOut.push_back(*work);
10786             }
10787         }
10788       previousArrI=*arrIPtr;
10789       *arrIPtr=(int)arrOut.size();
10790     }
10791   if(arr->getNumberOfTuples()==(int)arrOut.size())
10792     return false;
10793   arr->alloc((int)arrOut.size(),1);
10794   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10795   return true;
10796 }
10797
10798 /*!
10799  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10800  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10801  * The selection of extraction is done standardly in new2old format.
10802  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10803  *
10804  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10805  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10806  * \param [in] arrIn arr origin array from which the extraction will be done.
10807  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10808  * \param [out] arrOut the resulting array
10809  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10810  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10811  */
10812 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10813                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10814 {
10815   if(!arrIn || !arrIndxIn)
10816     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10817   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10818   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10819     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10820   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10821   const int *arrInPtr=arrIn->getConstPointer();
10822   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10823   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10824   if(nbOfGrps<0)
10825     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10826   int maxSizeOfArr=arrIn->getNumberOfTuples();
10827   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10829   arrIo->alloc((int)(sz+1),1);
10830   const int *idsIt=idsOfSelectBg;
10831   int *work=arrIo->getPointer();
10832   *work++=0;
10833   int lgth=0;
10834   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10835     {
10836       if(*idsIt>=0 && *idsIt<nbOfGrps)
10837         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10838       else
10839         {
10840           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10841           throw INTERP_KERNEL::Exception(oss.str().c_str());
10842         }
10843       if(lgth>=work[-1])
10844         *work=lgth;
10845       else
10846         {
10847           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10848           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10849           throw INTERP_KERNEL::Exception(oss.str().c_str());
10850         }
10851     }
10852   arro->alloc(lgth,1);
10853   work=arro->getPointer();
10854   idsIt=idsOfSelectBg;
10855   for(std::size_t i=0;i<sz;i++,idsIt++)
10856     {
10857       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10858         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10859       else
10860         {
10861           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10862           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10863           throw INTERP_KERNEL::Exception(oss.str().c_str());
10864         }
10865     }
10866   arrOut=arro.retn();
10867   arrIndexOut=arrIo.retn();
10868 }
10869
10870 /*!
10871  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10872  * 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 ).
10873  * The selection of extraction is done standardly in new2old format.
10874  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10875  *
10876  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10877  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10878  * \param [in] arrIn arr origin array from which the extraction will be done.
10879  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10880  * \param [out] arrOut the resulting array
10881  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10882  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10883  */
10884 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10885                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10886 {
10887   if(!arrIn || !arrIndxIn)
10888     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10889   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10890   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10891     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10892   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10893   const int *arrInPtr=arrIn->getConstPointer();
10894   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10895   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10896   if(nbOfGrps<0)
10897     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10898   int maxSizeOfArr=arrIn->getNumberOfTuples();
10899   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10900   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10901   arrIo->alloc((int)(sz+1),1);
10902   int idsIt=idsOfSelectStart;
10903   int *work=arrIo->getPointer();
10904   *work++=0;
10905   int lgth=0;
10906   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10907     {
10908       if(idsIt>=0 && idsIt<nbOfGrps)
10909         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10910       else
10911         {
10912           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10913           throw INTERP_KERNEL::Exception(oss.str().c_str());
10914         }
10915       if(lgth>=work[-1])
10916         *work=lgth;
10917       else
10918         {
10919           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10920           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10921           throw INTERP_KERNEL::Exception(oss.str().c_str());
10922         }
10923     }
10924   arro->alloc(lgth,1);
10925   work=arro->getPointer();
10926   idsIt=idsOfSelectStart;
10927   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10928     {
10929       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10930         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10931       else
10932         {
10933           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10934           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10935           throw INTERP_KERNEL::Exception(oss.str().c_str());
10936         }
10937     }
10938   arrOut=arro.retn();
10939   arrIndexOut=arrIo.retn();
10940 }
10941
10942 /*!
10943  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10944  * 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
10945  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10946  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10947  *
10948  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10949  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10950  * \param [in] arrIn arr origin array from which the extraction will be done.
10951  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10952  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10953  * \param [in] srcArrIndex index array of \b srcArr
10954  * \param [out] arrOut the resulting array
10955  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10956  * 
10957  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10958  */
10959 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10960                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10961                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10962 {
10963   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10964     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10965   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10966   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10967   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10968   std::vector<bool> v(nbOfTuples,true);
10969   int offset=0;
10970   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10971   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10972   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10973     {
10974       if(*it>=0 && *it<nbOfTuples)
10975         {
10976           v[*it]=false;
10977           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10978         }
10979       else
10980         {
10981           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10982           throw INTERP_KERNEL::Exception(oss.str().c_str());
10983         }
10984     }
10985   srcArrIndexPtr=srcArrIndex->getConstPointer();
10986   arrIo->alloc(nbOfTuples+1,1);
10987   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10988   const int *arrInPtr=arrIn->getConstPointer();
10989   const int *srcArrPtr=srcArr->getConstPointer();
10990   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10991   int *arroPtr=arro->getPointer();
10992   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10993     {
10994       if(v[ii])
10995         {
10996           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10997           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10998         }
10999       else
11000         {
11001           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11002           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11003           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11004         }
11005     }
11006   arrOut=arro.retn();
11007   arrIndexOut=arrIo.retn();
11008 }
11009
11010 /*!
11011  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11012  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11013  *
11014  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11015  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11016  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11017  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11018  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11019  * \param [in] srcArrIndex index array of \b srcArr
11020  * 
11021  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11022  */
11023 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11024                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11025 {
11026   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11027     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11028   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11029   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11030   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11031   int *arrInOutPtr=arrInOut->getPointer();
11032   const int *srcArrPtr=srcArr->getConstPointer();
11033   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11034     {
11035       if(*it>=0 && *it<nbOfTuples)
11036         {
11037           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11038             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11039           else
11040             {
11041               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] !";
11042               throw INTERP_KERNEL::Exception(oss.str().c_str());
11043             }
11044         }
11045       else
11046         {
11047           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11048           throw INTERP_KERNEL::Exception(oss.str().c_str());
11049         }
11050     }
11051 }
11052
11053 /*!
11054  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11055  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11056  * 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]].
11057  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11058  * A negative value in \b arrIn means that it is ignored.
11059  * 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.
11060  * 
11061  * \param [in] arrIn arr origin array from which the extraction will be done.
11062  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11063  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11064  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11065  */
11066 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11067 {
11068   int seed=0,nbOfDepthPeelingPerformed=0;
11069   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11070 }
11071
11072 /*!
11073  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11074  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11075  * 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]].
11076  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11077  * A negative value in \b arrIn means that it is ignored.
11078  * 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.
11079  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11080  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11081  * \param [in] arrIn arr origin array from which the extraction will be done.
11082  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11083  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11084  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11085  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11086  * \sa MEDCouplingUMesh::partitionBySpreadZone
11087  */
11088 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11089 {
11090   nbOfDepthPeelingPerformed=0;
11091   if(!arrIndxIn)
11092     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11093   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11094   if(nbOfTuples<=0)
11095     {
11096       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11097       return ret;
11098     }
11099   //
11100   std::vector<bool> fetched(nbOfTuples,false);
11101   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11102 }
11103
11104 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11105 {
11106   nbOfDepthPeelingPerformed=0;
11107   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11108     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11109   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11110   std::vector<bool> fetched2(nbOfTuples,false);
11111   int i=0;
11112   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11113     {
11114       if(*seedElt>=0 && *seedElt<nbOfTuples)
11115         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11116       else
11117         { std::ostringstream oss; oss << "MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : At pos #" << i << " of seeds value is " << *seedElt << "! Should be in [0," << nbOfTuples << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
11118     }
11119   const int *arrInPtr=arrIn->getConstPointer();
11120   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11121   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11122   std::vector<int> idsToFetch1(seedBg,seedEnd);
11123   std::vector<int> idsToFetch2;
11124   std::vector<int> *idsToFetch=&idsToFetch1;
11125   std::vector<int> *idsToFetchOther=&idsToFetch2;
11126   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11127     {
11128       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11129         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11130           if(!fetched[*it2])
11131             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11132       std::swap(idsToFetch,idsToFetchOther);
11133       idsToFetchOther->clear();
11134       nbOfDepthPeelingPerformed++;
11135     }
11136   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11137   i=0;
11138   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11139   int *retPtr=ret->getPointer();
11140   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11141     if(*it)
11142       *retPtr++=i;
11143   return ret.retn();
11144 }
11145
11146 /*!
11147  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11148  * 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
11149  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11150  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11151  *
11152  * \param [in] start begin of set of ids of the input extraction (included)
11153  * \param [in] end end of set of ids of the input extraction (excluded)
11154  * \param [in] step step of the set of ids in range mode.
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 [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11158  * \param [in] srcArrIndex index array of \b srcArr
11159  * \param [out] arrOut the resulting array
11160  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11161  * 
11162  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11163  */
11164 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11165                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11166                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11167 {
11168   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11169     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11170   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11171   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11172   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11173   int offset=0;
11174   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11175   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11176   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11177   int it=start;
11178   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11179     {
11180       if(it>=0 && it<nbOfTuples)
11181         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11182       else
11183         {
11184           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11185           throw INTERP_KERNEL::Exception(oss.str().c_str());
11186         }
11187     }
11188   srcArrIndexPtr=srcArrIndex->getConstPointer();
11189   arrIo->alloc(nbOfTuples+1,1);
11190   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11191   const int *arrInPtr=arrIn->getConstPointer();
11192   const int *srcArrPtr=srcArr->getConstPointer();
11193   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11194   int *arroPtr=arro->getPointer();
11195   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11196     {
11197       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11198       if(pos<0)
11199         {
11200           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11201           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11202         }
11203       else
11204         {
11205           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11206           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11207         }
11208     }
11209   arrOut=arro.retn();
11210   arrIndexOut=arrIo.retn();
11211 }
11212
11213 /*!
11214  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11215  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11216  *
11217  * \param [in] start begin of set of ids of the input extraction (included)
11218  * \param [in] end end of set of ids of the input extraction (excluded)
11219  * \param [in] step step of the set of ids in range mode.
11220  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11221  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11222  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11223  * \param [in] srcArrIndex index array of \b srcArr
11224  * 
11225  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11226  */
11227 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11228                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11229 {
11230   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11231     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11232   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11233   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11234   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11235   int *arrInOutPtr=arrInOut->getPointer();
11236   const int *srcArrPtr=srcArr->getConstPointer();
11237   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11238   int it=start;
11239   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11240     {
11241       if(it>=0 && it<nbOfTuples)
11242         {
11243           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11244             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11245           else
11246             {
11247               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11248               throw INTERP_KERNEL::Exception(oss.str().c_str());
11249             }
11250         }
11251       else
11252         {
11253           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11254           throw INTERP_KERNEL::Exception(oss.str().c_str());
11255         }
11256     }
11257 }
11258
11259 /*!
11260  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11261  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11262  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11263  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11264  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11265  * 
11266  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11267  */
11268 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11269 {
11270   checkFullyDefined();
11271   int mdim=getMeshDimension();
11272   int spaceDim=getSpaceDimension();
11273   if(mdim!=spaceDim)
11274     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11275   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11276   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11277   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11278   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11279   ret->setCoords(getCoords());
11280   ret->allocateCells((int)partition.size());
11281   //
11282   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11283     {
11284       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11285       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11286       switch(mdim)
11287       {
11288         case 2:
11289           cell=tmp->buildUnionOf2DMesh();
11290           break;
11291         case 3:
11292           cell=tmp->buildUnionOf3DMesh();
11293           break;
11294         default:
11295           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11296       }
11297
11298       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11299     }
11300   //
11301   ret->finishInsertingCells();
11302   return ret.retn();
11303 }
11304
11305 /*!
11306  * This method partitions \b this into contiguous zone.
11307  * This method only needs a well defined connectivity. Coordinates are not considered here.
11308  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11309  */
11310 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11311 {
11312   int nbOfCellsCur=getNumberOfCells();
11313   std::vector<DataArrayInt *> ret;
11314   if(nbOfCellsCur<=0)
11315     return ret;
11316   DataArrayInt *neigh=0,*neighI=0;
11317   computeNeighborsOfCells(neigh,neighI);
11318   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11319   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11320   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11321   int seed=0;
11322   while(seed<nbOfCellsCur)
11323     {
11324       int nbOfPeelPerformed=0;
11325       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11326       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11327     }
11328   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11329     ret.push_back((*it).retn());
11330   return ret;
11331 }
11332
11333 /*!
11334  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11335  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11336  *
11337  * \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.
11338  * \return a newly allocated DataArrayInt to be managed by the caller.
11339  * \throw In case of \a code has not the right format (typically of size 3*n)
11340  */
11341 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11342 {
11343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11344   std::size_t nb=code.size()/3;
11345   if(code.size()%3!=0)
11346     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11347   ret->alloc((int)nb,2);
11348   int *retPtr=ret->getPointer();
11349   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11350     {
11351       retPtr[0]=code[3*i+2];
11352       retPtr[1]=code[3*i+2]+code[3*i+1];
11353     }
11354   return ret.retn();
11355 }
11356
11357 /*!
11358  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11359  * All cells in \a this are expected to be linear 3D cells.
11360  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11361  * It leads to an increase to number of cells.
11362  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11363  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11364  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11365  *
11366  * \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.
11367  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11368  * \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. 
11369  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11370  *          an id of old cell producing it. The caller is to delete this array using
11371  *         decrRef() as it is no more needed.
11372  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11373  *
11374  * \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
11375  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11376  * 
11377  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11378  * \throw If \a this is not fully constituted with linear 3D cells.
11379  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11380  */
11381 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11382 {
11383   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11384   checkConnectivityFullyDefined();
11385   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11386     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11387   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11388   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11390   int *retPt(ret->getPointer());
11391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11392   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11393   const int *oldc(_nodal_connec->begin());
11394   const int *oldci(_nodal_connec_index->begin());
11395   const double *coords(_coords->begin());
11396   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11397     {
11398       std::vector<int> a; std::vector<double> b;
11399       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11400       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11401       const int *aa(&a[0]);
11402       if(!b.empty())
11403         {
11404           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11405             if(*it<0)
11406               *it=(-(*(it))-1+nbNodes);
11407           addPts->insertAtTheEnd(b.begin(),b.end());
11408           nbNodes+=(int)b.size()/3;
11409         }
11410       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11411         newConn->insertAtTheEnd(aa,aa+4);
11412     }
11413   if(!addPts->empty())
11414     {
11415       addPts->rearrange(3);
11416       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11417       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11418       ret0->setCoords(addPts);
11419     }
11420   else
11421     {
11422       nbOfAdditionalPoints=0;
11423       ret0->setCoords(getCoords());
11424     }
11425   ret0->setNodalConnectivity(newConn);
11426   //
11427   ret->computeOffsets2();
11428   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11429   return ret0.retn();
11430 }
11431
11432 /*!
11433  * 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). 
11434  *
11435  * \sa MEDCouplingUMesh::split2DCells
11436  */
11437 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11438 {
11439   checkConnectivityFullyDefined();
11440   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11441   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11442   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11443   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11444   int prevPosOfCi(ciPtr[0]);
11445   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11446     {
11447       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11448       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11449       for(int j=0;j<sz;j++)
11450         {
11451           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11452           for(int k=0;k<sz2;k++)
11453             *cPtr++=subPtr[offset2+k];
11454           if(j!=sz-1)
11455             *cPtr++=oldConn[prevPosOfCi+j+2];
11456           deltaSz+=sz2;
11457         }
11458       prevPosOfCi=ciPtr[1];
11459       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11460     }
11461   if(c->end()!=cPtr)
11462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11463   _nodal_connec->decrRef();
11464   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11465 }
11466
11467 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11468 {
11469   if(id!=-1)
11470     return id;
11471   else
11472     {
11473       int ret(nodesCnter++);
11474       double newPt[2];
11475       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11476       addCoo.insertAtTheEnd(newPt,newPt+2);
11477       return ret;
11478     }
11479 }
11480
11481 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11482 {
11483   if(id!=-1)
11484     return id;
11485   else
11486     {
11487       int ret(nodesCnter++);
11488       double newPt[2];
11489       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11490       addCoo.insertAtTheEnd(newPt,newPt+2);
11491       return ret;
11492     }
11493 }
11494
11495
11496 /// @cond INTERNAL
11497
11498 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)
11499 {
11500   int tmp[3];
11501   int trueStart(start>=0?start:nbOfEdges+start);
11502   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11503   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11504   if(linOrArc)
11505     {
11506       if(stp-start>1)
11507         {
11508           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11509           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11510           middles.push_back(tmp3+offset);
11511         }
11512       else
11513         middles.push_back(connBg[trueStart+nbOfEdges]);
11514     }
11515 }
11516
11517 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)
11518 {
11519   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11520   newConnOfCell->pushBackSilent(tmpEnd);
11521   if(linOrArc)
11522     {
11523       if(stp-start>1)
11524         {
11525           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11526           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11527           middles.push_back(tmp3+offset);
11528         }
11529       else
11530         middles.push_back(connBg[start+nbOfEdges]);
11531     }
11532 }
11533
11534 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)
11535 {
11536   // only the quadratic point to deal with:
11537   if(linOrArc)
11538     {
11539       if(stp-start>1)
11540         {
11541           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11542           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11543           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11544           middles.push_back(tmp3+offset);
11545         }
11546       else
11547         middles.push_back(connBg[start+nbOfEdges]);
11548     }
11549 }
11550
11551 /// @cond INTERNAL
11552
11553 /*!
11554  * 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 ) .
11555  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11556  */
11557 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11558 {
11559   std::size_t sz(std::distance(connBg,connEnd));
11560   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11561     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11562   sz--;
11563   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11564   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11565   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11566   unsigned nbOfHit(0); // number of fusions operated
11567   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11568   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
11569   INTERP_KERNEL::NormalizedCellType typeOfSon;
11570   std::vector<int> middles;
11571   bool ret(false);
11572   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11573     {
11574       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11575       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11576       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11577       posEndElt = posBaseElt+1;
11578
11579       // Look backward first: are the final edges of the cells colinear with the first ones?
11580       // This initializes posBaseElt.
11581       if(nbOfTurn==0)
11582         {
11583           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11584             {
11585               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11586               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11587               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11588               bool isColinear=eint->areColinears();
11589               if(isColinear)
11590                 {
11591                   nbOfHit++;
11592                   posBaseElt--;
11593                   ret=true;
11594                 }
11595               delete eint;
11596               eCand->decrRef();
11597               if(!isColinear)
11598                 break;
11599             }
11600         }
11601       // Now move forward:
11602       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11603       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11604         {
11605           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11606           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11607           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11608           bool isColinear(eint->areColinears());
11609           if(isColinear)
11610             {
11611               nbOfHit++;
11612               posEndElt++;
11613               ret=true;
11614             }
11615           delete eint;
11616           eCand->decrRef();
11617           if(!isColinear)
11618               break;
11619         }
11620       //push [posBaseElt,posEndElt) in newConnOfCell using e
11621       // 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!
11622       if(nbOfTurn==0)
11623         // at the begining of the connectivity (insert type)
11624         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11625       else if((nbOfHit+nbOfTurn) != (nbs-1))
11626         // in the middle
11627         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11628       if ((nbOfHit+nbOfTurn) == (nbs-1))
11629         // at the end (only quad points to deal with)
11630         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11631       posBaseElt=posEndElt;
11632       e->decrRef();
11633     }
11634   if(!middles.empty())
11635     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11636   return ret;
11637 }
11638
11639 /*!
11640  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11641  *
11642  * \return  int - the number of new nodes created.
11643  * \sa MEDCouplingUMesh::split2DCells
11644  */
11645 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11646 {
11647   checkCoherency();
11648   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11649   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11650   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11651   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11652   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11653   const double *oldCoordsPtr(getCoords()->begin());
11654   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11655   int prevPosOfCi(ciPtr[0]);
11656   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11657     {
11658       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11659       for(int j=0;j<sz;j++)
11660         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11661       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11662       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11663         {
11664           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11665           if(sz2==0)
11666             {
11667               if(j<sz-1)
11668                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11669               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11670               continue;
11671             }
11672           std::vector<INTERP_KERNEL::Node *> ns(3);
11673           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11674           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11675           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11676           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11677           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11678             {
11679               cPtr[1]=subPtr[offset2+k];
11680               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11681             }
11682           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11683           if(j!=sz-1)
11684             { cPtr[1]=tmpEnd; }
11685           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11686         }
11687       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11688       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11689     }
11690   if(c->end()!=cPtr)
11691     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11692   _nodal_connec->decrRef();
11693   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11694   addCoo->rearrange(2);
11695   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11696   setCoords(coo);
11697   return addCoo->getNumberOfTuples();
11698 }
11699
11700 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11701 {
11702   if(nodalConnec && nodalConnecIndex)
11703     {
11704       types.clear();
11705       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11706       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11707       if(nbOfElem>0)
11708         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11709           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11710     }
11711 }
11712
11713 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11714     _own_cell(true),_cell_id(-1),_nb_cell(0)
11715 {
11716   if(mesh)
11717     {
11718       mesh->incrRef();
11719       _nb_cell=mesh->getNumberOfCells();
11720     }
11721 }
11722
11723 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11724 {
11725   if(_mesh)
11726     _mesh->decrRef();
11727   if(_own_cell)
11728     delete _cell;
11729 }
11730
11731 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11732     _own_cell(false),_cell_id(bg-1),
11733     _nb_cell(end)
11734 {
11735   if(mesh)
11736     mesh->incrRef();
11737 }
11738
11739 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11740 {
11741   _cell_id++;
11742   if(_cell_id<_nb_cell)
11743     {
11744       _cell->next();
11745       return _cell;
11746     }
11747   else
11748     return 0;
11749 }
11750
11751 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11752 {
11753   if(_mesh)
11754     _mesh->incrRef();
11755 }
11756
11757 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11758 {
11759   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11760 }
11761
11762 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11763 {
11764   if(_mesh)
11765     _mesh->decrRef();
11766 }
11767
11768 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11769     _itc(itc),
11770     _bg(bg),_end(end)
11771 {
11772   if(_mesh)
11773     _mesh->incrRef();
11774 }
11775
11776 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11777 {
11778   if(_mesh)
11779     _mesh->decrRef();
11780 }
11781
11782 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11783 {
11784   return _type;
11785 }
11786
11787 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11788 {
11789   return _end-_bg;
11790 }
11791
11792 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11793 {
11794   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11795 }
11796
11797 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11798 {
11799   if(mesh)
11800     {
11801       mesh->incrRef();
11802       _nb_cell=mesh->getNumberOfCells();
11803     }
11804 }
11805
11806 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11807 {
11808   if(_mesh)
11809     _mesh->decrRef();
11810   delete _cell;
11811 }
11812
11813 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11814 {
11815   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11816   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11817   if(_cell_id<_nb_cell)
11818     {
11819       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11820       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11821       int startId=_cell_id;
11822       _cell_id+=nbOfElems;
11823       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11824     }
11825   else
11826     return 0;
11827 }
11828
11829 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11830 {
11831   if(mesh)
11832     {
11833       _conn=mesh->getNodalConnectivity()->getPointer();
11834       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11835     }
11836 }
11837
11838 void MEDCouplingUMeshCell::next()
11839 {
11840   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11841     {
11842       _conn+=_conn_lgth;
11843       _conn_indx++;
11844     }
11845   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11846 }
11847
11848 std::string MEDCouplingUMeshCell::repr() const
11849 {
11850   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11851     {
11852       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11853       oss << " : ";
11854       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11855       return oss.str();
11856     }
11857   else
11858     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11859 }
11860
11861 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11862 {
11863   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11864     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11865   else
11866     return INTERP_KERNEL::NORM_ERROR;
11867 }
11868
11869 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11870 {
11871   lgth=_conn_lgth;
11872   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11873     return _conn;
11874   else
11875     return 0;
11876 }